Merge branch 'feature-heat-exchangers' into 'develop'

ENH: fvOptions: refactor and extend effectivenessHeatExchangerSource

See merge request Development/openfoam!557
This commit is contained in:
Andrew Heather
2022-09-07 13:55:01 +00:00
10 changed files with 1423 additions and 337 deletions

View File

@ -13,7 +13,6 @@ $(derivedSources)/actuationDiskSource/actuationDiskSource.C
$(derivedSources)/buoyancyEnergy/buoyancyEnergy.C
$(derivedSources)/buoyancyForce/buoyancyForce.C
$(derivedSources)/directionalPressureGradientExplicitSource/directionalPressureGradientExplicitSource.C
$(derivedSources)/effectivenessHeatExchangerSource/effectivenessHeatExchangerSource.C
$(derivedSources)/explicitPorositySource/explicitPorositySource.C
$(derivedSources)/jouleHeatingSource/jouleHeatingSource.C
$(derivedSources)/meanVelocityForce/meanVelocityForce.C
@ -38,6 +37,12 @@ $(derivedSources)/viscousDissipation/viscousDissipation.C
$(derivedSources)/buoyancyTurbSource/buoyancyTurbSource.C
$(derivedSources)/patchCellsSource/patchCellsSource.C
$(derivedSources)/heatExchangerSource/heatExchangerSource.C
$(derivedSources)/heatExchangerSource/heatExchangerModels/heatExchangerModel/heatExchangerModel.C
$(derivedSources)/heatExchangerSource/heatExchangerModels/heatExchangerModel/heatExchangerModelNew.C
$(derivedSources)/heatExchangerSource/heatExchangerModels/effectivenessTable/effectivenessTable.C
$(derivedSources)/heatExchangerSource/heatExchangerModels/referenceTemperature/referenceTemperature.C
interRegion = sources/interRegion
$(interRegion)/interRegionHeatTransfer/interRegionHeatTransferModel/interRegionHeatTransferModel.C
$(interRegion)/interRegionHeatTransfer/constantHeatTransfer/constantHeatTransfer.C

View File

@ -5,8 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2013-2015 OpenFOAM Foundation
Copyright (C) 2016-2022 OpenCFD Ltd.
Copyright (C) 2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -26,114 +25,42 @@ License
\*---------------------------------------------------------------------------*/
#include "effectivenessHeatExchangerSource.H"
#include "fvMesh.H"
#include "fvMatrix.H"
#include "addToRunTimeSelectionTable.H"
#include "effectivenessTable.H"
#include "basicThermo.H"
#include "coupledPolyPatch.H"
#include "surfaceInterpolate.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace fv
namespace heatExchangerModels
{
defineTypeNameAndDebug(effectivenessHeatExchangerSource, 0);
defineTypeNameAndDebug(effectivenessTable, 0);
addToRunTimeSelectionTable
(
option,
effectivenessHeatExchangerSource,
heatExchangerModel,
effectivenessTable,
dictionary
);
}
}
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::fv::effectivenessHeatExchangerSource::initialise()
void Foam::heatExchangerModels::effectivenessTable::writeFileHeader
(
Ostream& os
) const
{
const label zoneID = mesh_.faceZones().findZoneID(faceZoneName_);
if (zoneID < 0)
{
FatalErrorInFunction
<< type() << " " << this->name() << ": "
<< " Unknown face zone name: " << faceZoneName_
<< ". Valid face zones are: " << mesh_.faceZones().names()
<< exit(FatalError);
}
const faceZone& fZone = mesh_.faceZones()[zoneID];
faceId_.setSize(fZone.size());
facePatchId_.setSize(fZone.size());
faceSign_.setSize(fZone.size());
label count = 0;
forAll(fZone, i)
{
const label facei = fZone[i];
label faceId = -1;
label facePatchId = -1;
if (mesh_.isInternalFace(facei))
{
faceId = facei;
facePatchId = -1;
}
else
{
facePatchId = mesh_.boundaryMesh().whichPatch(facei);
const polyPatch& pp = mesh_.boundaryMesh()[facePatchId];
const auto* cpp = isA<coupledPolyPatch>(pp);
if (cpp)
{
faceId = (cpp->owner() ? pp.whichFace(facei) : -1);
}
else if (!isA<emptyPolyPatch>(pp))
{
faceId = pp.whichFace(facei);
}
else
{
faceId = -1;
facePatchId = -1;
}
}
if (faceId >= 0)
{
if (fZone.flipMap()[i])
{
faceSign_[count] = -1;
}
else
{
faceSign_[count] = 1;
}
faceId_[count] = faceId;
facePatchId_[count] = facePatchId;
count++;
}
}
faceId_.setSize(count);
facePatchId_.setSize(count);
faceSign_.setSize(count);
}
void Foam::fv::effectivenessHeatExchangerSource::writeFileHeader(Ostream& os)
{
writeFile::writeHeader(os, "Effectiveness heat exchanger source");
writeFile::writeHeader(os, "Heat exchanger source");
writeFile::writeCommented(os, "Time");
writeFile::writeTabbed(os, "Net mass flux [kg/s]");
writeFile::writeTabbed(os, "Total heat exchange [W]");
writeFile::writeTabbed(os, "Secondary inlet T [K]");
writeFile::writeTabbed(os, "Tref [K]");
writeFile::writeTabbed(os, "Effectiveness");
writeFile::writeTabbed(os, "Reference T [K]");
writeFile::writeTabbed(os, "Effectiveness [-]");
if (secondaryCpPtr_)
{
@ -146,16 +73,14 @@ void Foam::fv::effectivenessHeatExchangerSource::writeFileHeader(Ostream& os)
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::fv::effectivenessHeatExchangerSource::effectivenessHeatExchangerSource
Foam::heatExchangerModels::effectivenessTable::effectivenessTable
(
const fvMesh& mesh,
const word& name,
const word& modelType,
const dictionary& dict,
const fvMesh& mesh
const dictionary& coeffs
)
:
fv::cellSetOption(name, modelType, dict, mesh),
writeFile(mesh, name, modelType, coeffs_),
heatExchangerModel(mesh, name, coeffs),
userPrimaryInletT_(false),
targetQdotActive_(false),
secondaryCpPtr_
@ -163,7 +88,7 @@ Foam::fv::effectivenessHeatExchangerSource::effectivenessHeatExchangerSource
Function1<scalar>::NewIfPresent
(
"secondaryCp",
coeffs_,
coeffs,
word::null,
&mesh
)
@ -175,40 +100,29 @@ Foam::fv::effectivenessHeatExchangerSource::effectivenessHeatExchangerSource
primaryInletT_(0),
targetQdot_(0),
targetQdotRelax_(0.5),
UName_("U"),
TName_("T"),
phiName_("phi"),
faceZoneName_("unknown-faceZone"),
faceId_(),
facePatchId_(),
faceSign_()
sumPhi_(0),
Qt_(0),
Tref_(0),
effectiveness_(0)
{
read(dict);
// Set the field name to that of the energy
// field from which the temperature is obtained
const auto& thermo = mesh_.lookupObject<basicThermo>(basicThermo::dictName);
fieldNames_.resize(1, thermo.he().name());
fv::option::resetApplied();
eTable_.reset(new interpolation2DTable<scalar>(coeffs_));
initialise();
writeFileHeader(file());
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
void Foam::fv::effectivenessHeatExchangerSource::addSup
void Foam::heatExchangerModels::effectivenessTable::initialise()
{
eTable_.reset(new interpolation2DTable<scalar>(coeffs_));
heatExchangerModel::initialise();
}
Foam::tmp<Foam::scalarField>
Foam::heatExchangerModels::effectivenessTable::energyDensity
(
const volScalarField& rho,
fvMatrix<scalar>& eqn,
const label
const labelList& cells
)
{
const auto& thermo = mesh_.lookupObject<basicThermo>(basicThermo::dictName);
@ -218,7 +132,7 @@ void Foam::fv::effectivenessHeatExchangerSource::addSup
const surfaceScalarField Cpf(fvc::interpolate(thermo.Cp()));
const surfaceScalarField Tf(fvc::interpolate(T));
scalar sumPhi = 0;
sumPhi_ = 0;
scalar sumMagPhi = 0;
scalar CpfMean = 0;
scalar primaryInletTfMean = 0;
@ -231,7 +145,7 @@ void Foam::fv::effectivenessHeatExchangerSource::addSup
const scalar phii = phi.boundaryField()[patchi][facei]*faceSign_[i];
const scalar magPhii = mag(phii);
sumPhi += phii;
sumPhi_ += phii;
sumMagPhi += magPhii;
const scalar Cpfi = Cpf.boundaryField()[patchi][facei];
@ -245,7 +159,7 @@ void Foam::fv::effectivenessHeatExchangerSource::addSup
const scalar phii = phi[facei]*faceSign_[i];
const scalar magPhii = mag(phii);
sumPhi += phii;
sumPhi_ += phii;
sumMagPhi += magPhii;
CpfMean += Cpf[facei]*magPhii;
@ -253,8 +167,9 @@ void Foam::fv::effectivenessHeatExchangerSource::addSup
}
}
reduce(CpfMean, sumOp<scalar>());
reduce(sumPhi, sumOp<scalar>());
reduce(sumPhi_, sumOp<scalar>());
reduce(sumMagPhi, sumOp<scalar>());
CpfMean /= sumMagPhi + ROOTVSMALL;
scalar primaryInletT = primaryInletT_;
@ -264,11 +179,11 @@ void Foam::fv::effectivenessHeatExchangerSource::addSup
primaryInletT = primaryInletTfMean/(sumMagPhi + ROOTVSMALL);
}
const scalar effectiveness = eTable_()(mag(sumPhi), secondaryMassFlowRate_);
effectiveness_ = eTable_()(mag(sumPhi_), secondaryMassFlowRate_);
const scalar alpha = effectiveness*CpfMean*mag(sumPhi);
const scalar alpha = effectiveness_*CpfMean*mag(sumPhi_);
const scalar Qt = alpha*(secondaryInletT_ - primaryInletT);
Qt_ = alpha*(secondaryInletT_ - primaryInletT);
if
(
@ -276,84 +191,144 @@ void Foam::fv::effectivenessHeatExchangerSource::addSup
&& (mesh_.time().timeIndex() % targetQdotCalcInterval_ == 0)
)
{
const scalar dT = (targetQdot_ - Qt)/(alpha + ROOTVSMALL);
const scalar dT = (targetQdot_ - Qt_)/(alpha + ROOTVSMALL);
secondaryInletT_ += targetQdotRelax_*dT;
}
const scalarField TCells(T, cells_);
scalar Tref = 0;
scalarField deltaTCells(cells_.size(), Zero);
if (Qt > 0)
const scalarField TCells(T, cells);
scalarField deltaTCells(cells.size(), Zero);
Tref_ = 0;
if (Qt_ > 0)
{
Tref = gMax(TCells);
Tref_ = gMax(TCells);
forAll(deltaTCells, i)
{
deltaTCells[i] = max(Tref - TCells[i], scalar(0));
deltaTCells[i] = max(Tref_ - TCells[i], scalar(0));
}
}
else
{
Tref = gMin(TCells);
Tref_ = gMin(TCells);
forAll(deltaTCells, i)
{
deltaTCells[i] = max(TCells[i] - Tref, scalar(0));
deltaTCells[i] = max(TCells[i] - Tref_, scalar(0));
}
}
const auto& U = mesh_.lookupObject<volVectorField>(UName_);
const scalarField& V = mesh_.V();
scalar sumWeight = 0;
forAll(cells_, i)
forAll(cells, i)
{
const label celli = cells_[i];
const label celli = cells[i];
sumWeight += V[celli]*mag(U[celli])*deltaTCells[i];
}
reduce(sumWeight, sumOp<scalar>());
if (this->V() > VSMALL && mag(Qt) > VSMALL)
{
scalarField& heSource = eqn.source();
return Qt_*deltaTCells/(sumWeight + ROOTVSMALL);
}
forAll(cells_, i)
{
const label celli = cells_[i];
heSource[celli] -=
Qt*V[celli]*mag(U[celli])*deltaTCells[i]
/(sumWeight + ROOTVSMALL);
}
bool Foam::heatExchangerModels::effectivenessTable::read(const dictionary& dict)
{
if (!writeFile::read(dict))
{
return false;
}
Log << nl
<< type() << ": " << name() << nl << incrIndent
<< indent << "Net mass flux [kg/s] : " << sumPhi << nl
<< indent << "Total heat exchange [W] : " << Qt << nl
<< indent << "Secondary inlet T [K] : " << secondaryInletT_ << nl
<< indent << "Tref [K] : " << Tref << nl
<< indent << "Effectiveness : " << effectiveness
<< decrIndent;
Info<< incrIndent << indent << "- using model: " << type() << endl;
coeffs_.readEntry("secondaryMassFlowRate", secondaryMassFlowRate_);
coeffs_.readEntry("secondaryInletT", secondaryInletT_);
if (coeffs_.readIfPresent("primaryInletT", primaryInletT_))
{
userPrimaryInletT_ = true;
Info<< indent
<< "- using user-specified primary flow inlet temperature: "
<< primaryInletT_ << endl;
}
else
{
Info<< indent
<< "- using flux-weighted primary flow inlet temperature"
<< endl;
}
if (coeffs_.readIfPresent("targetQdot", targetQdot_))
{
targetQdotActive_ = true;
Info<< indent << "- using target heat rejection: " << targetQdot_ << nl;
coeffs_.readIfPresent
(
"targetQdotCalcInterval",
targetQdotCalcInterval_
);
Info<< indent << "- updating secondary inlet temperature every "
<< targetQdotCalcInterval_ << " iterations" << nl;
coeffs_.readIfPresent("targetQdotRelax", targetQdotRelax_);
Info<< indent << "- temperature relaxation: "
<< targetQdotRelax_ << endl;
}
UName_ = coeffs_.getOrDefault<word>("U", "U");
TName_ = coeffs_.getOrDefault<word>("T", "T");
phiName_ = coeffs_.getOrDefault<word>("phi", "phi");
coeffs_.readEntry("faceZone", faceZoneName_);
Info<< decrIndent;
return true;
}
void Foam::heatExchangerModels::effectivenessTable::write
(
const bool log
)
{
if (log)
{
Info<< nl
<< type() << ": " << name_ << nl << incrIndent
<< indent << "Net mass flux [kg/s] : " << sumPhi_ << nl
<< indent << "Total heat exchange [W] : " << Qt_ << nl
<< indent << "Secondary inlet T [K] : " << secondaryInletT_<< nl
<< indent << "Reference T [K] : " << Tref_ << nl
<< indent << "Effectiveness [-] : " << effectiveness_
<< decrIndent;
}
if (Pstream::master())
{
Ostream& os = file();
writeCurrentTime(os);
os << tab << sumPhi
<< tab << Qt
os << tab << sumPhi_
<< tab << Qt_
<< tab << secondaryInletT_
<< tab << Tref
<< tab << effectiveness;
<< tab << Tref_
<< tab << effectiveness_;
if (secondaryCpPtr_)
{
// Secondary Cp as a function of the starting secondary temperature
const scalar secondaryCp = secondaryCpPtr_->value(secondaryInletT_);
const scalar secondaryOutletT =
Qt/(secondaryMassFlowRate_*secondaryCp) + secondaryInletT_;
Qt_/(secondaryMassFlowRate_*secondaryCp) + secondaryInletT_;
Log << nl << incrIndent << indent
<< "Secondary outlet T [K] : " << secondaryOutletT
<< decrIndent;
if (log)
{
Info << nl << incrIndent << indent
<< "Secondary outlet T [K] : " << secondaryOutletT
<< decrIndent;
}
os << tab << secondaryOutletT;
}
@ -364,58 +339,4 @@ void Foam::fv::effectivenessHeatExchangerSource::addSup
}
bool Foam::fv::effectivenessHeatExchangerSource::read(const dictionary& dict)
{
if (!(fv::cellSetOption::read(dict) && writeFile::read(dict)))
{
return false;
}
coeffs_.readEntry("secondaryMassFlowRate", secondaryMassFlowRate_);
coeffs_.readEntry("secondaryInletT", secondaryInletT_);
if (coeffs_.readIfPresent("primaryInletT", primaryInletT_))
{
userPrimaryInletT_ = true;
Info<< type() << " " << this->name() << ": " << indent << nl
<< "employing user-specified primary flow inlet temperature: "
<< primaryInletT_ << endl;
}
else
{
Info<< type() << " " << this->name() << ": " << indent << nl
<< "employing flux-weighted primary flow inlet temperature"
<< endl;
}
if (coeffs_.readIfPresent("targetQdot", targetQdot_))
{
targetQdotActive_ = true;
Info<< indent << "employing target heat rejection of "
<< targetQdot_ << nl;
coeffs_.readIfPresent
(
"targetQdotCalcInterval",
targetQdotCalcInterval_
);
Info<< indent << "updating secondary inlet temperature every "
<< targetQdotCalcInterval_ << " iterations" << nl;
coeffs_.readIfPresent("targetQdotRelax", targetQdotRelax_);
Info<< indent << "temperature relaxation: "
<< targetQdotRelax_ << endl;
}
UName_ = coeffs_.getOrDefault<word>("U", "U");
TName_ = coeffs_.getOrDefault<word>("T", "T");
phiName_ = coeffs_.getOrDefault<word>("phi", "phi");
coeffs_.readEntry("faceZone", faceZoneName_);
return true;
}
// ************************************************************************* //

View File

@ -5,8 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2013-2017 OpenFOAM Foundation
Copyright (C) 2016-2022 OpenCFD Ltd.
Copyright (C) 2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -25,18 +24,15 @@ License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::fv::effectivenessHeatExchangerSource
Group
grpFvOptionsSources
Foam::heatExchangerModels::effectivenessTable
Description
Heat exchanger source model for compressible flows, where the heat
exchanger is modelled as an energy source using a selection of cells.
A heat exchanger model where heat exchange
is calculated via an effectiveness table.
The total heat exchange source is given by:
\f[
Q_t = e(\phi, \dot{m}_2) (T_2 - T_1) \phi c_p
Q_t = e(\phi, \dot{m}_2) (T_2 - T_1) \phi C_p
\f]
where:
@ -47,10 +43,9 @@ Description
\dot{m}_2 | Secondary flow mass flow rate [kg/s]
T_1 | Primary flow inlet temperature [K]
T_2 | Secondary flow inlet temperature [K]
c_p | Primary flow specific heat capacity [J/kg/K]
C_p | Primary flow specific heat capacity [J/kg/K]
\endvartable
The distribution inside the heat exchanger is given by:
\f[
Q_c = \frac{V_c |U_c| (T_c - T_{ref})}{\sum(V_c |U_c| (T_c - T_{ref}))}
@ -59,42 +54,26 @@ Description
where:
\vartable
Q_c | Source for cell
V_c | Volume of the cell [m3]
V_c | Volume of the cell [m^3]
U_c | Local cell velocity [m/s]
T_c | Local cell temperature [K]
T_{ref} | Min or max(T) in cell zone depending on the sign of Qt [K]
\endvartable
Sources applied to either of the below, if exist:
\verbatim
e | Internal energy [m2/s2]
h | Enthalphy [m2/s2]
\endverbatim
Required fields:
\verbatim
T | Temperature [K]
U | Velocity [m/s]
phi | Mass flux [kg/s]
\endverbatim
Usage
Minimal example by using \c constant/fvOptions:
\verbatim
effectivenessHeatExchangerSource1
<name>
{
// Inherited entries
...
// Mandatory entries
type effectivenessHeatExchangerSource;
faceZone <faceZoneName>;
model effectivenessTable;
secondaryMassFlowRate <scalar>;
secondaryInletT <scalar>;
file "effectivenessTable";
outOfBounds clamp;
// Optional entries
U <word>;
T <word>;
phi <word>;
file "<word>";
outOfBounds <word>;
// Conditional optional entries
@ -108,23 +87,17 @@ Usage
// when secondary outlet temperature is requested
secondaryCp <Function1<scalar>>;
// Inherited entries
...
}
\endverbatim
where the entries mean:
\table
Property | Description | Type | Reqd | Deflt
type | Type name: effectivenessHeatExchangerSource <!--
--> | word | yes | -
secondaryMassFlowRate | Secondary flow mass rate [kg/s] <!--
model | Model name:effectivenessTable | word | yes | -
secondaryMassFlowRate | Secondary flow mass rate [kg/s] <!--
--> | scalar | yes | -
secondaryInletT | Secondary flow inlet temperature [K] <!--
secondaryInletT | Secondary flow inlet temperature [K] <!--
--> | scalar | yes | -
faceZone | Name of the faceZone at the heat exchanger inlet <!--
--> | word | yes | -
file | 2D effectiveness table = function of primary <!--
--> and secondary mass flow rates [kg/s] | file | yes | -
primaryInletT | Primary flow temperature at the heat exchanger inlet <!--
@ -136,16 +109,11 @@ Usage
--> under-relaxation coefficient | scalar | no | -
secondaryCp | Secondary flow specific heat capacity <!--
--> | Function1\<scalar\> | no | -
U | Name of operand velocity field | word | no | U
T | Name of operand temperature field | word | no | T
phi | Name of operand flux field | word | no | phi
\endtable
The inherited entries are elaborated in:
- \link fvOption.H \endlink
- \link cellSetOption.H \endlink
- \link writeFile.H \endlink
- \link Function1.H \endlink
- \link heatExchangerSource.H \endlink
- \link interpolation2DTable.H \endlink
The effectiveness table is described in terms of the primary and secondary
mass flow rates. For example, the table:
@ -202,34 +170,31 @@ Note
flux-averaged temperature is used.
SourceFiles
effectivenessHeatExchangerSource.C
effectivenessTable.C
\*---------------------------------------------------------------------------*/
#ifndef fv_effectivenessHeatExchangerSource_H
#define fv_effectivenessHeatExchangerSource_H
#ifndef Foam_heatExchangerModels_effectivenessTable_H
#define Foam_heatExchangerModels_effectivenessTable_H
#include "cellSetOption.H"
#include "autoPtr.H"
#include "heatExchangerModel.H"
#include "interpolation2DTable.H"
#include "writeFile.H"
#include "Function1.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace fv
namespace heatExchangerModels
{
/*---------------------------------------------------------------------------*\
Class effectivenessHeatExchangerSource Declaration
Class effectivenessTable Declaration
\*---------------------------------------------------------------------------*/
class effectivenessHeatExchangerSource
class effectivenessTable
:
public fv::cellSetOption,
public functionObjects::writeFile
public heatExchangerModel
{
// Private Data
@ -264,100 +229,78 @@ class effectivenessHeatExchangerSource
//- Target heat rejection temperature under-relaxation coefficient
scalar targetQdotRelax_;
//- Name of operand velocity field
word UName_;
//- Net mass flux [kg/s]
scalar sumPhi_;
//- Name of operand temperature field
word TName_;
//- Total heat exchange [W]
scalar Qt_;
//- Name of operand flux field
word phiName_;
//- Reference temperature [K]
scalar Tref_;
//- Name of the faceZone at the heat exchanger inlet
word faceZoneName_;
//- Local list of face IDs
labelList faceId_;
//- Local list of patch IDs per face
labelList facePatchId_;
//- List of +1/-1 representing face flip map (1 use as is, -1 negate)
labelList faceSign_;
//- Effectiveness of the heat exchanger [-]
scalar effectiveness_;
// Private Member Functions
//- Initialise heat exchanger source model
void initialise();
// I-O
//- Output file header information
virtual void writeFileHeader(Ostream& os);
//- Write file header information
void writeFileHeader(Ostream& os) const;
public:
//- Runtime type information
TypeName("effectivenessHeatExchangerSource");
TypeName("effectivenessTable");
// Constructors
//- Construct from components
effectivenessHeatExchangerSource
effectivenessTable
(
const fvMesh& mesh,
const word& name,
const word& modelType,
const dictionary& dict,
const fvMesh& mesh
const dictionary& coeffs
);
//- No copy construct
effectivenessHeatExchangerSource
(
const effectivenessHeatExchangerSource&
) = delete;
effectivenessTable(const effectivenessTable&) = delete;
//- No copy assignment
void operator=(const effectivenessHeatExchangerSource&) = delete;
void operator=(const effectivenessTable&) = delete;
//- Destructor
virtual ~effectivenessHeatExchangerSource() = default;
virtual ~effectivenessTable() = default;
// Member Functions
//- Add explicit/implicit contribution to momentum equation
virtual void addSup
(
fvMatrix<scalar>& eqn,
const label fieldi
)
{
NotImplemented;
}
// Evaluation
//- Add explicit/implicit contribution
//- to compressible momentum equation
virtual void addSup
(
const volScalarField& rho,
fvMatrix<scalar>& eqn,
const label fieldi
);
//- Initialise data members of the model
virtual void initialise();
//- Return energy density per unit length [J/m3/m]
virtual tmp<scalarField> energyDensity(const labelList& cells);
// I-O
// I-O
//- Read dictionary
virtual bool read(const dictionary& dict);
//- Read top-level dictionary
virtual bool read(const dictionary& dict);
//- Write data to stream and files
virtual void write(const bool log);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace fv
} // End namespace heatExchangerModels
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -0,0 +1,138 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 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 "heatExchangerModel.H"
#include "coupledPolyPatch.H"
#include "surfaceInterpolate.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(heatExchangerModel, 0);
defineRunTimeSelectionTable(heatExchangerModel, dictionary);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::heatExchangerModel::heatExchangerModel
(
const fvMesh& mesh,
const word& name,
const dictionary& coeffs
)
:
writeFile(mesh, name, typeName, coeffs),
mesh_(mesh),
coeffs_(coeffs),
name_(name),
UName_("U"),
TName_("T"),
phiName_("phi"),
faceZoneName_("unknown-faceZone"),
faceId_(),
facePatchId_(),
faceSign_()
{}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
void Foam::heatExchangerModel::initialise()
{
const label zoneID = mesh_.faceZones().findZoneID(faceZoneName_);
if (zoneID < 0)
{
FatalErrorInFunction
<< type() << " " << name_ << ": "
<< " Unknown face zone name: " << faceZoneName_
<< ". Valid face zones are: " << mesh_.faceZones().names()
<< exit(FatalError);
}
const faceZone& fZone = mesh_.faceZones()[zoneID];
faceId_.setSize(fZone.size());
facePatchId_.setSize(fZone.size());
faceSign_.setSize(fZone.size());
label count = 0;
forAll(fZone, i)
{
const label facei = fZone[i];
label faceId = -1;
label facePatchId = -1;
if (mesh_.isInternalFace(facei))
{
faceId = facei;
facePatchId = -1;
}
else
{
facePatchId = mesh_.boundaryMesh().whichPatch(facei);
const polyPatch& pp = mesh_.boundaryMesh()[facePatchId];
const auto* cpp = isA<coupledPolyPatch>(pp);
if (cpp)
{
faceId = (cpp->owner() ? pp.whichFace(facei) : -1);
}
else if (!isA<emptyPolyPatch>(pp))
{
faceId = pp.whichFace(facei);
}
else
{
faceId = -1;
facePatchId = -1;
}
}
if (faceId >= 0)
{
if (fZone.flipMap()[i])
{
faceSign_[count] = -1;
}
else
{
faceSign_[count] = 1;
}
faceId_[count] = faceId;
facePatchId_[count] = facePatchId;
count++;
}
}
faceId_.setSize(count);
facePatchId_.setSize(count);
faceSign_.setSize(count);
}
// ************************************************************************* //

View File

@ -0,0 +1,191 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 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/>.
Namespace
Foam::heatExchangerModels
Description
A namespace for various heat exchanger model implementations.
Class
Foam::heatExchangerModel
Description
Base class for heat exchanger models to handle various
characteristics for the \c heatExchangerSource fvOption.
SourceFiles
heatExchangerModel.C
heatExchangerModelNew.C
\*---------------------------------------------------------------------------*/
#ifndef Foam_heatExchangerModel_H
#define Foam_heatExchangerModel_H
#include "fvMesh.H"
#include "writeFile.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class heatExchangerModel Declaration
\*---------------------------------------------------------------------------*/
class heatExchangerModel
:
public functionObjects::writeFile
{
protected:
// Protected Data
//- Reference to the mesh
const fvMesh& mesh_;
//- Dictionary containing coefficients specific to the chosen model
const dictionary& coeffs_;
//- Reference to the name of the fvOption source
const word& name_;
//- Name of operand velocity field
word UName_;
//- Name of operand temperature field
word TName_;
//- Name of operand flux field
word phiName_;
//- Name of the faceZone at the heat exchanger inlet
word faceZoneName_;
//- Local list of face IDs
labelList faceId_;
//- Local list of patch IDs per face
labelList facePatchId_;
//- List of +1/-1 representing face flip map (1 use as is, -1 negate)
labelList faceSign_;
public:
//- Runtime type information
TypeName("heatExchangerModel");
// Declare runtime constructor selection table
declareRunTimeSelectionTable
(
autoPtr,
heatExchangerModel,
dictionary,
(
const fvMesh& mesh,
const word& name,
const dictionary& coeffs
),
(mesh, name, coeffs)
);
// Selectors
//- Return a reference to the selected heat exchanger model
static autoPtr<heatExchangerModel> New
(
const fvMesh& mesh,
const word& name,
const dictionary& coeffs
);
// Constructors
//- Construct from components
heatExchangerModel
(
const fvMesh& mesh,
const word& name,
const dictionary& coeffs
);
//- No copy construct
heatExchangerModel(const heatExchangerModel&) = delete;
//- No copy assignment
void operator=(const heatExchangerModel&) = delete;
//- Destructor
virtual ~heatExchangerModel() = default;
// Member Functions
// Access
//- Return const reference to the name of velocity field
virtual const word& U() const
{
return UName_;
}
// Evaluation
//- Initialise data members of the model
virtual void initialise();
//- Return energy density per unit length [J/m3/m]
virtual tmp<scalarField> energyDensity(const labelList& cells) = 0;
// I-O
//- Read top-level dictionary
virtual bool read(const dictionary& dict) = 0;
//- Write data to stream and files
virtual void write(const bool log) = 0;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,58 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 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 "heatExchangerModel.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Foam::autoPtr<Foam::heatExchangerModel> Foam::heatExchangerModel::New
(
const fvMesh& mesh,
const word& name,
const dictionary& coeffs
)
{
const word modelType(coeffs.get<word>("model"));
auto* ctorPtr = dictionaryConstructorTable(modelType);
if (!ctorPtr)
{
FatalIOErrorInLookup
(
coeffs,
"heatExchangerModel",
modelType,
*dictionaryConstructorTablePtr_
) << exit(FatalIOError);
}
return autoPtr<heatExchangerModel>(ctorPtr(mesh, name, coeffs));
}
// ************************************************************************* //

View File

@ -0,0 +1,311 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 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 "referenceTemperature.H"
#include "fvMesh.H"
#include "basicThermo.H"
#include "surfaceInterpolate.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace heatExchangerModels
{
defineTypeNameAndDebug(referenceTemperature, 0);
addToRunTimeSelectionTable
(
heatExchangerModel,
referenceTemperature,
dictionary
);
}
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
Foam::scalar
Foam::heatExchangerModels::referenceTemperature::primaryNetMassFlux() const
{
const auto& phi = mesh_.lookupObject<surfaceScalarField>(phiName_);
scalar sumPhi = 0;
forAll(faceId_, i)
{
const label facei = faceId_[i];
if (facePatchId_[i] != -1)
{
const label patchi = facePatchId_[i];
sumPhi += phi.boundaryField()[patchi][facei]*faceSign_[i];
}
else
{
sumPhi += phi[facei]*faceSign_[i];
}
}
reduce(sumPhi, sumOp<scalar>());
return sumPhi;
}
Foam::scalar
Foam::heatExchangerModels::referenceTemperature::primaryInletTemperature() const
{
const auto& phi = mesh_.lookupObject<surfaceScalarField>(phiName_);
const auto& T = mesh_.lookupObject<volScalarField>(TName_);
const surfaceScalarField Tf(fvc::interpolate(T));
scalar sumMagPhi = 0;
scalar primaryInletTfMean = 0;
forAll(faceId_, i)
{
const label facei = faceId_[i];
if (facePatchId_[i] != -1)
{
const label patchi = facePatchId_[i];
const scalar phii = phi.boundaryField()[patchi][facei]*faceSign_[i];
const scalar magPhii = mag(phii);
sumMagPhi += magPhii;
const scalar Tfi = Tf.boundaryField()[patchi][facei];
primaryInletTfMean += Tfi*magPhii;
}
else
{
const scalar phii = phi[facei]*faceSign_[i];
const scalar magPhii = mag(phii);
sumMagPhi += magPhii;
primaryInletTfMean += Tf[facei]*magPhii;
}
}
reduce(sumMagPhi, sumOp<scalar>());
reduce(primaryInletTfMean, sumOp<scalar>());
return primaryInletTfMean/(sumMagPhi + ROOTVSMALL);
}
Foam::scalarField
Foam::heatExchangerModels::referenceTemperature::temperatureDifferences
(
const labelList& cells
) const
{
const auto& T = mesh_.lookupObject<volScalarField>(TName_);
const scalarField TCells(T, cells);
scalarField deltaTCells(cells.size(), Zero);
if (Qt_ > 0)
{
forAll(deltaTCells, i)
{
deltaTCells[i] = max(Tref_ - TCells[i], scalar(0));
}
}
else
{
forAll(deltaTCells, i)
{
deltaTCells[i] = max(TCells[i] - Tref_, scalar(0));
}
}
return deltaTCells;
}
Foam::scalar
Foam::heatExchangerModels::referenceTemperature::weight
(
const labelList& cells,
const scalarField& deltaTCells
) const
{
scalar sumWeight = 0;
const auto& U = mesh_.lookupObject<volVectorField>(UName_);
const scalarField& V = mesh_.V();
forAll(cells, i)
{
const label celli = cells[i];
sumWeight += V[celli]*mag(U[celli])*deltaTCells[i];
}
reduce(sumWeight, sumOp<scalar>());
return sumWeight;
}
void Foam::heatExchangerModels::referenceTemperature::writeFileHeader
(
Ostream& os
) const
{
writeFile::writeHeader(os, "Effectiveness heat exchanger source");
writeFile::writeCommented(os, "Time");
writeFile::writeTabbed(os, "Net mass flux [kg/s]");
writeFile::writeTabbed(os, "Total heat exchange [W]");
writeFile::writeTabbed(os, "Reference T [K]");
os << endl;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::heatExchangerModels::referenceTemperature::referenceTemperature
(
const fvMesh& mesh,
const word& name,
const dictionary& coeffs
)
:
heatExchangerModel(mesh, name, coeffs),
targetQdotPtr_
(
Function1<scalar>::New
(
"targetQdot",
coeffs,
&mesh_
)
),
TrefTablePtr_(nullptr),
sumPhi_(0),
Qt_(0),
Tref_(0)
{
writeFileHeader(file());
}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
void Foam::heatExchangerModels::referenceTemperature::initialise()
{
heatExchangerModel::initialise();
}
Foam::tmp<Foam::scalarField>
Foam::heatExchangerModels::referenceTemperature::energyDensity
(
const labelList& cells
)
{
sumPhi_ = primaryNetMassFlux();
Qt_ = targetQdotPtr_->value(mesh_.time().value());
if (TrefTablePtr_)
{
const scalar primaryInletT = primaryInletTemperature();
Tref_ = TrefTablePtr_()(mag(sumPhi_), primaryInletT);
}
const scalarField deltaTCells(temperatureDifferences(cells));
const scalar sumWeight = weight(cells, deltaTCells);
return Qt_*deltaTCells/(sumWeight + ROOTVSMALL);
}
bool Foam::heatExchangerModels::referenceTemperature::read
(
const dictionary& dict
)
{
if (!writeFile::read(dict))
{
return false;
}
Info<< incrIndent << indent << "- using model: " << type() << endl;
if (coeffs_.readIfPresent("Tref", Tref_))
{
Info<< indent << "- using constant reference temperature: " << Tref_
<< endl;
}
else
{
TrefTablePtr_.reset(new interpolation2DTable<scalar>(coeffs_));
Info<< indent << "- using reference temperature table"
<< endl;
}
UName_ = coeffs_.getOrDefault<word>("U", "U");
TName_ = coeffs_.getOrDefault<word>("T", "T");
phiName_ = coeffs_.getOrDefault<word>("phi", "phi");
coeffs_.readEntry("faceZone", faceZoneName_);
Info<< decrIndent;
return true;
}
void Foam::heatExchangerModels::referenceTemperature::write(const bool log)
{
if (log)
{
Info<< nl
<< type() << ": " << name_ << nl << incrIndent
<< indent << "Net mass flux [kg/s] : " << sumPhi_ << nl
<< indent << "Total heat exchange [W] : " << Qt_ << nl
<< indent << "Reference T [K] : " << Tref_
<< decrIndent;
}
if (Pstream::master())
{
Ostream& os = file();
writeCurrentTime(os);
os << tab << sumPhi_
<< tab << Qt_
<< tab << Tref_
<< endl;
}
if (log) Info<< nl << endl;
}
// ************************************************************************* //

View File

@ -0,0 +1,202 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 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::heatExchangerModels::referenceTemperature
Description
A heat exchanger model where heat exchange
is calculated via a temperature table.
Usage
Minimal example by using \c constant/fvOptions:
\verbatim
<name>
{
// Inherited entries
...
// Mandatory entries
model referenceTemperature;
targetQdot <Function1<scalar>>;
// Conditional mandatory entries
// Option-1
Tref <scalar>;
// Option-2
file "<word>";
}
\endverbatim
where the entries mean:
\table
Property | Description | Type | Reqd | Deflt
model | Model name:effectivenessTable | word | yes | -
targetQdot | Target heat rejection [J/s] <!--
--> | Function1\<scalar\> | yes | -
Tref | Reference temperature [K] | scalar | choice | -
file | 2D reference temperature table = function of primary <!--
--> mass flow rate [kg/s] and primary flow temperature <!--
--> | file | choice | -
\endtable
The inherited entries are elaborated in:
- \link heatExchangerSource.H \endlink
- \link interpolation2DTable.H \endlink
SourceFiles
referenceTemperature.C
\*---------------------------------------------------------------------------*/
#ifndef Foam_heatExchangerModels_referenceTemperature_H
#define Foam_heatExchangerModels_referenceTemperature_H
#include "heatExchangerModel.H"
#include "interpolation2DTable.H"
#include "Function1.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace heatExchangerModels
{
/*---------------------------------------------------------------------------*\
Class referenceTemperature Declaration
\*---------------------------------------------------------------------------*/
class referenceTemperature
:
public heatExchangerModel
{
// Private Data
//- Target heat rejection [J/s]
autoPtr<Function1<scalar>> targetQdotPtr_;
//- 2D reference temperature table
//- Function of primary mass flow rate [kg/s]
//- and primary flow temperature [K]
autoPtr<interpolation2DTable<scalar>> TrefTablePtr_;
//- Net mass flux [kg/s]
scalar sumPhi_;
//- Total heat exchange [J/s]
scalar Qt_;
//- Reference temperature [K]
scalar Tref_;
// Private Member Functions
// Evaluation
//- Return primary-flow net mass flux
scalar primaryNetMassFlux() const;
//- Return primary-flow inlet temperature
scalar primaryInletTemperature() const;
//- Return temperature differences
scalarField temperatureDifferences(const labelList& cells) const;
//- Return interim weights
scalar weight
(
const labelList& cells,
const scalarField& deltaTCells
) const;
// I-O
//- Write file header information
void writeFileHeader(Ostream& os) const;
public:
//- Runtime type information
TypeName("referenceTemperature");
// Constructors
//- Construct from components
referenceTemperature
(
const fvMesh& mesh,
const word& name,
const dictionary& coeffs
);
//- No copy construct
referenceTemperature(const referenceTemperature&) = delete;
//- No copy assignment
void operator=(const referenceTemperature&) = delete;
//- Destructor
virtual ~referenceTemperature() = default;
// Member Functions
// Evaluation
//- Initialise data members of the model
virtual void initialise();
//- Return energy density per unit length [J/m3/m]
virtual tmp<scalarField> energyDensity(const labelList& cells);
// I-O
//- Read top-level dictionary
virtual bool read(const dictionary& dict);
//- Write data to stream and files
virtual void write(const bool log);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace heatExchangerModels
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,116 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2013-2015 OpenFOAM Foundation
Copyright (C) 2016-2022 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 "heatExchangerSource.H"
#include "heatExchangerModel.H"
#include "fvMatrix.H"
#include "basicThermo.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace fv
{
defineTypeNameAndDebug(heatExchangerSource, 0);
addToRunTimeSelectionTable(option, heatExchangerSource, dictionary);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::fv::heatExchangerSource::heatExchangerSource
(
const word& name,
const word& modelType,
const dictionary& dict,
const fvMesh& mesh
)
:
fv::cellSetOption(name, modelType, dict, mesh),
heatExchangerModelPtr_(heatExchangerModel::New(mesh, name, coeffs_))
{
read(dict);
// Set the field name to that of the energy
// field from which the temperature is obtained
const auto& thermo = mesh_.lookupObject<basicThermo>(basicThermo::dictName);
fieldNames_.resize(1, thermo.he().name());
fv::option::resetApplied();
heatExchangerModelPtr_->initialise();
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::fv::heatExchangerSource::addSup
(
const volScalarField& rho,
fvMatrix<scalar>& eqn,
const label
)
{
const scalarField Q(heatExchangerModelPtr_->energyDensity(cells_));
if (this->V() > VSMALL)
{
const word& UName = heatExchangerModelPtr_->U();
const auto& U = mesh_.lookupObject<volVectorField>(UName);
const scalarField& V = mesh_.V();
scalarField& heSource = eqn.source();
forAll(cells_, i)
{
const label celli = cells_[i];
heSource[celli] -= Q[i]*V[celli]*mag(U[celli]);
}
}
heatExchangerModelPtr_->write(log);
}
bool Foam::fv::heatExchangerSource::read(const dictionary& dict)
{
if (!fv::cellSetOption::read(dict) || !heatExchangerModelPtr_->read(dict))
{
return false;
}
return true;
}
// ************************************************************************* //

View File

@ -0,0 +1,201 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2013-2017 OpenFOAM Foundation
Copyright (C) 2016-2022 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::fv::heatExchangerSource
Group
grpFvOptionsSources
Description
Heat exchanger source model for compressible flows, where the heat
exchanger is modelled as an energy source using a selection of cells.
Sources applied to either of the below, if exist:
\verbatim
e | Internal energy [m2/s2]
h | Enthalphy [m2/s2]
\endverbatim
Required fields:
\verbatim
T | Temperature [K]
U | Velocity [m/s]
phi | Mass flux [kg/s]
\endverbatim
Usage
Minimal example by using \c constant/fvOptions:
\verbatim
<name>
{
// Mandatory entries
type heatExchangerSource;
model <word>;
faceZone <word>;
// Conditional entries
// Option-1: when model == effectivenessTable
// Option-2: when model == referenceTemperature
// Optional entries
U <word>;
T <word>;
phi <word>;
// Inherited entries
...
}
\endverbatim
where the entries mean:
\table
Property | Description | Type | Reqd | Deflt
type | Type name: heatExchangerSource | word | yes | -
model | Name of the heat exchanger model | word | yes | -
faceZone | Name of the faceZone at the heat exchanger inlet <!--
--> | word | yes | -
U | Name of operand velocity field | word | no | U
T | Name of operand temperature field | word | no | T
phi | Name of operand flux field | word | no | phi
\endtable
Options for the \c model entry:
\verbatim
effectivenessTable | Calculate heat exchange via an effectiveness table
referenceTemperature | Calculate heat exchange via a temperature table
\endverbatim
The inherited entries are elaborated in:
- \link fvOption.H \endlink
- \link cellSetOption.H \endlink
- \link writeFile.H \endlink
- \link Function1.H \endlink
SourceFiles
heatExchangerSource.C
\*---------------------------------------------------------------------------*/
#ifndef Foam_fv_heatExchangerSource_H
#define Foam_fv_heatExchangerSource_H
#include "cellSetOption.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward Declarations
class heatExchangerModel;
namespace fv
{
/*---------------------------------------------------------------------------*\
Class heatExchangerSource Declaration
\*---------------------------------------------------------------------------*/
class heatExchangerSource
:
public fv::cellSetOption
{
// Private Data
//- Heat exchanger model
autoPtr<heatExchangerModel> heatExchangerModelPtr_;
public:
//- Runtime type information
TypeName("heatExchangerSource");
// Constructors
//- Construct from components
heatExchangerSource
(
const word& name,
const word& modelType,
const dictionary& dict,
const fvMesh& mesh
);
//- No copy construct
heatExchangerSource(const heatExchangerSource&) = delete;
//- No copy assignment
void operator=(const heatExchangerSource&) = delete;
//- Destructor
virtual ~heatExchangerSource() = default;
// Member Functions
//- Add explicit/implicit contribution to momentum equation
virtual void addSup
(
fvMatrix<scalar>& eqn,
const label fieldi
)
{
NotImplemented;
}
//- Add explicit/implicit contribution
//- to compressible momentum equation
virtual void addSup
(
const volScalarField& rho,
fvMatrix<scalar>& eqn,
const label fieldi
);
// I-O
//- Read top-level dictionary
virtual bool read(const dictionary& dict);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace fv
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //