ENH: radiometerProbes: new function object to monitor radiative heat flux at internal points
The radiometer probes enable measurement of incident radiative heat flux at arbitrary internal points within the domain, useful for radiation sensor simulation and heat transfer analysis in participating media applications.
This commit is contained in:
@ -57,6 +57,7 @@ writeDictionary/writeDictionary.C
|
||||
writeObjects/writeObjects.C
|
||||
|
||||
thermoCoupleProbes/thermoCoupleProbes.C
|
||||
radiometerProbes/radiometerProbes.C
|
||||
|
||||
syncObjects/syncObjects.C
|
||||
|
||||
|
||||
@ -9,7 +9,9 @@ EXE_INC = \
|
||||
-I$(LIB_SRC)/sampling/lnInclude \
|
||||
-I$(LIB_SRC)/ODE/lnInclude \
|
||||
-I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \
|
||||
-I$(LIB_SRC)/transportModels/compressible/lnInclude
|
||||
-I$(LIB_SRC)/transportModels/compressible/lnInclude \
|
||||
-I$(LIB_SRC)/thermophysicalModels/radiation/lnInclude \
|
||||
-I$(LIB_SRC)/parallel/distributed/lnInclude
|
||||
|
||||
LIB_LIBS = \
|
||||
-lfiniteVolume \
|
||||
@ -22,4 +24,6 @@ LIB_LIBS = \
|
||||
-lsampling \
|
||||
-lODE \
|
||||
-lfluidThermophysicalModels \
|
||||
-lcompressibleTransportModels
|
||||
-lcompressibleTransportModels \
|
||||
-lradiationModels \
|
||||
-ldistributed
|
||||
|
||||
@ -0,0 +1,260 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2025 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 "radiometerProbes.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace functionObjects
|
||||
{
|
||||
defineTypeNameAndDebug(radiometerProbes, 0);
|
||||
addToRunTimeSelectionTable(functionObject, radiometerProbes, dictionary);
|
||||
}
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::functionObjects::radiometerProbes::writeFileHeader(Ostream& os)
|
||||
{
|
||||
const pointField& locs = probeLocations();
|
||||
|
||||
writeCommented(os, "Probe,Location,Normal");
|
||||
|
||||
os << nl;
|
||||
for (label i = 0; i < szProbes_; ++i)
|
||||
{
|
||||
const vector& loc = locs[i];
|
||||
const vector& n = n_[i];
|
||||
|
||||
os << '#' << ' ' << i
|
||||
<< ',' << loc.x() << ',' << loc.y() << ',' << loc.z()
|
||||
<< ',' << n.x() << ',' << n.y() << ',' << n.z()
|
||||
<< nl;
|
||||
}
|
||||
|
||||
os << "# Time";
|
||||
for (int i = 0; i < szProbes_; ++i)
|
||||
{
|
||||
os << ',' << i;
|
||||
}
|
||||
os << endl;
|
||||
|
||||
writtenHeader_ = true;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::functionObjects::radiometerProbes::radiometerProbes
|
||||
(
|
||||
const word& name,
|
||||
const Time& runTime,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
regionFunctionObject(name, runTime, dict),
|
||||
internalProber(mesh_, dict),
|
||||
writeFile(mesh_, name, typeName, dict),
|
||||
dom_(mesh_.lookupObject<radiation::fvDOM>("radiationProperties")),
|
||||
firstIter_(true)
|
||||
{
|
||||
read(dict);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Public Member Functions * * * * * * * * * * * //
|
||||
|
||||
bool Foam::functionObjects::radiometerProbes::read(const dictionary& dict)
|
||||
{
|
||||
if
|
||||
(
|
||||
!(
|
||||
regionFunctionObject::read(dict)
|
||||
&& internalProber::read(dict)
|
||||
&& writeFile::read(dict)
|
||||
)
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Skip if the radiation model is inactive
|
||||
if (!dom_.radiation())
|
||||
{
|
||||
WarningInFunction
|
||||
<< "The radiation model is inactive."
|
||||
<< "Skipping the function object " << type() << ' ' << name()
|
||||
<< endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
Log << type() << ':' << name() << ": read" << nl << nl;
|
||||
|
||||
|
||||
// Probe locations are read by 'internalProber'
|
||||
szProbes_ = this->size();
|
||||
|
||||
// If/when fvDOM is updated, the 'read' func is assumed to be executed to
|
||||
// update the fvDOM properties
|
||||
nRay_ = dom_.nRay();
|
||||
|
||||
if (!szProbes_ || !nRay_)
|
||||
{
|
||||
FatalIOErrorInFunction(dict)
|
||||
<< "size(probe locations): " << szProbes_ << nl
|
||||
<< "size(rays): " << nRay_ << nl
|
||||
<< "The input size of probe locations and rays cannot be zero."
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
// Read and check size consistency of probe normals with probe locations
|
||||
dict.readEntry("probeNormals", n_);
|
||||
if (n_.size() != szProbes_)
|
||||
{
|
||||
FatalIOErrorInFunction(dict)
|
||||
<< "size(probe locations): " << szProbes_ << nl
|
||||
<< "size(probe normals): " << n_.size() << nl
|
||||
<< "The input size of probe locations and normals must match."
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
n_.normalise();
|
||||
|
||||
|
||||
// Pre-compute and cache inner product of 'n_' and 'dAve_', and 'C_'
|
||||
// This simplification of calculation is valid only if I is non-negative
|
||||
n_dAve_.resize(nRay_);
|
||||
C_.resize(nRay_);
|
||||
|
||||
for (label rayi = 0; rayi < nRay_; ++rayi)
|
||||
{
|
||||
const vector& dAvei = dom_.IRay(rayi).dAve();
|
||||
|
||||
scalarList& n_dAveRay = n_dAve_[rayi];
|
||||
boolList& Cray = C_[rayi];
|
||||
|
||||
n_dAveRay.resize(szProbes_, Zero);
|
||||
Cray.resize(szProbes_, false);
|
||||
|
||||
for (label pi = 0; pi < szProbes_; ++pi)
|
||||
{
|
||||
n_dAveRay[pi] = n_[pi] & dAvei;
|
||||
|
||||
if (n_dAveRay[pi] < 0) // ray entering the probe
|
||||
{
|
||||
Cray[pi] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qin_.resize(szProbes_);
|
||||
|
||||
|
||||
if (writeFile::canResetFile())
|
||||
{
|
||||
writeFile::resetFile(typeName);
|
||||
}
|
||||
|
||||
if (writeFile::canWriteHeader())
|
||||
{
|
||||
writeFileHeader(file());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::functionObjects::radiometerProbes::execute()
|
||||
{
|
||||
// Skip if there is no probe to sample, or the radiation model is inactive
|
||||
if (!szProbes_ || !dom_.radiation() || !shouldCalcThisStep())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Log << type() << ' ' << name() << ": execute" << nl << nl;
|
||||
|
||||
qin_ = Zero; // resized in 'read'
|
||||
|
||||
for (label rayi = 0; rayi < nRay_; ++rayi)
|
||||
{
|
||||
// Radiative intensity field for this ray
|
||||
const volScalarField& I = dom_.IRay(rayi).I();
|
||||
|
||||
// Sample radiative intensity ray at probe locations
|
||||
tmp<scalarField> tIp = internalProber::sample(I);
|
||||
const scalarField& Ip = tIp.cref();
|
||||
|
||||
const scalarList& n_dAveRay = n_dAve_[rayi];
|
||||
const boolList& Cray = C_[rayi];
|
||||
|
||||
// Add incident radiative heat flux per probe location for each ray
|
||||
for (label pi = 0; pi < szProbes_; ++pi)
|
||||
{
|
||||
if (Cray[pi])
|
||||
{
|
||||
qin_[pi] += Ip[pi]*n_dAveRay[pi];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::functionObjects::radiometerProbes::write()
|
||||
{
|
||||
// Skip if there is no probe to sample, or the radiation model is inactive
|
||||
if (!szProbes_ || !dom_.radiation() || !shouldCalcThisStep())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Log << type() << ' ' << name() << ": write" << nl << nl;
|
||||
|
||||
if (UPstream::master())
|
||||
{
|
||||
Ostream& os = file();
|
||||
|
||||
os << mesh_.time().timeOutputValue();
|
||||
for (label pi = 0; pi < szProbes_; ++pi)
|
||||
{
|
||||
os << ',' << qin_[pi];
|
||||
}
|
||||
os << endl;
|
||||
}
|
||||
|
||||
firstIter_ = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,200 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2025 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/>.
|
||||
|
||||
Class
|
||||
Foam::functionObjects::radiometerProbes
|
||||
|
||||
Group
|
||||
grpUtilitiesFunctionObjects
|
||||
|
||||
Description
|
||||
Probes the incident radiative heat flux, qin, at arbitrary points within a
|
||||
domain.
|
||||
|
||||
Usage
|
||||
Minimal example by using \c system/controlDict.functions:
|
||||
\verbatim
|
||||
radiometer
|
||||
{
|
||||
// Mandatory entries
|
||||
type radiometerProbes;
|
||||
libs (utilityFunctionObjects);
|
||||
probeLocations (<vectorList>);
|
||||
probeNormals (<vectorList>);
|
||||
|
||||
// Inherited entries
|
||||
...
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
where the entries mean:
|
||||
\table
|
||||
Property | Description | Type | Reqd | Deflt
|
||||
type | Type name: radiometerProbes | word | yes | -
|
||||
libs | Library name: utilityFunctionObjects | word | yes | -
|
||||
probeLocations | Locations of probes | vectorList | yes | -
|
||||
probeNormals | Normals of specified probes | vectorList | yes | -
|
||||
\endtable
|
||||
|
||||
The inherited entries are elaborated in:
|
||||
- \link regionFunctionObject.H \endlink
|
||||
- \link internalProber.H \endlink
|
||||
- \link writeFile.H \endlink
|
||||
- \link fvDOM.H \endlink
|
||||
|
||||
Note
|
||||
- The function object can only be used with the \c fvDOM radiation model.
|
||||
- The \c solverFreq input of the \c fvDOM model has superiority over
|
||||
\c executeControl and \c writeControl entries.
|
||||
|
||||
SourceFiles
|
||||
radiometerProbes.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_functionObjects_radiometerProbes_H
|
||||
#define Foam_functionObjects_radiometerProbes_H
|
||||
|
||||
#include "regionFunctionObject.H"
|
||||
#include "internalProber.H"
|
||||
#include "writeFile.H"
|
||||
#include "fvDOM.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace functionObjects
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class radiometerProbes Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class radiometerProbes
|
||||
:
|
||||
public regionFunctionObject,
|
||||
public internalProber,
|
||||
public writeFile
|
||||
{
|
||||
// Private Data
|
||||
|
||||
//- Const reference to the underlying radiation model
|
||||
const radiation::fvDOM& dom_;
|
||||
|
||||
//- Normal vectors of the specified probes
|
||||
vectorField n_;
|
||||
|
||||
//- Pre-computed inner product of probe normals (n_) and average
|
||||
//- solid-angle direction (dAve) per radiative intensity ray
|
||||
List<scalarList> n_dAve_;
|
||||
|
||||
//- Directional selection coefficient for radiative intensity rays
|
||||
// false: ray entering the probe
|
||||
// true: ray leaving the probe
|
||||
List<boolList> C_;
|
||||
|
||||
//- Incident radiative heat flux per probe location
|
||||
scalarField qin_;
|
||||
|
||||
//- Number of radiative intensity rays
|
||||
label nRay_;
|
||||
|
||||
//- Number of probe locations/normals
|
||||
label szProbes_;
|
||||
|
||||
//- Flag to identify whether the iteration is the first iteration
|
||||
// Resets with a restarted simulation
|
||||
bool firstIter_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Write file-header information into the output file
|
||||
virtual void writeFileHeader(Ostream& os);
|
||||
|
||||
//- Return the flag to decide if radiation-model calculations are
|
||||
//- performed, so that function object calculations can proceed
|
||||
bool shouldCalcThisStep() const
|
||||
{
|
||||
return
|
||||
firstIter_
|
||||
|| (mesh_.time().timeIndex() % dom_.solverFreq() == 0);
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("radiometerProbes");
|
||||
|
||||
|
||||
// Generated Methods
|
||||
|
||||
//- No copy construct
|
||||
radiometerProbes(const radiometerProbes&) = delete;
|
||||
|
||||
//- No copy assignment
|
||||
void operator=(const radiometerProbes&) = delete;
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from name, Time and dictionary
|
||||
radiometerProbes
|
||||
(
|
||||
const word& name,
|
||||
const Time& runTime,
|
||||
const dictionary& dict
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~radiometerProbes() = default;
|
||||
|
||||
|
||||
// Public Member Functions
|
||||
|
||||
//- Read the function object settings
|
||||
virtual bool read(const dictionary&);
|
||||
|
||||
//- Execute the function object
|
||||
virtual bool execute();
|
||||
|
||||
//- Write to data files/fields and to streams
|
||||
virtual bool write();
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace functionObjects
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
Reference in New Issue
Block a user