fvOptions::effectivenessHeatExchangerSource: Updated to use Function2

This commit is contained in:
Henry Weller
2020-11-13 16:38:26 +00:00
parent b2bf6f3733
commit df4e94d173
6 changed files with 43 additions and 704 deletions

View File

@ -1,436 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2019 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 "FoamTableReader.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Type>
Foam::interpolation2DTable<Type>::interpolation2DTable()
:
List<Tuple2<scalar, List<Tuple2<scalar, Type>>>>(),
boundsHandling_(interpolation2DTable::WARN),
fileName_(fileName::null),
reader_(nullptr)
{}
template<class Type>
Foam::interpolation2DTable<Type>::interpolation2DTable
(
const List<Tuple2<scalar, List<Tuple2<scalar, Type>>>>& values,
const boundsHandling bounds,
const fileName& fName
)
:
List<Tuple2<scalar, List<Tuple2<scalar, Type>>>>(values),
boundsHandling_(bounds),
fileName_(fName),
reader_(nullptr)
{}
template<class Type>
Foam::interpolation2DTable<Type>::interpolation2DTable(const fileName& fName)
:
List<Tuple2<scalar, List<Tuple2<scalar, Type>>>>(),
boundsHandling_(interpolation2DTable::WARN),
fileName_(fName),
reader_(new TableReaders::Foam<Type>(dictionary()))
{
reader_()(fileName_, *this);
checkOrder();
}
template<class Type>
Foam::interpolation2DTable<Type>::interpolation2DTable(const dictionary& dict)
:
List<Tuple2<scalar, List<Tuple2<scalar, Type>>>>(),
boundsHandling_(wordToBoundsHandling(dict.lookup("outOfBounds"))),
fileName_(dict.lookup("file")),
reader_(new TableReaders::Foam<Type>(dictionary()))
{
reader_()(fileName_, *this);
checkOrder();
}
template<class Type>
Foam::interpolation2DTable<Type>::interpolation2DTable
(
const interpolation2DTable& interpTable
)
:
List<Tuple2<scalar, List<Tuple2<scalar, Type>>>>(interpTable),
boundsHandling_(interpTable.boundsHandling_),
fileName_(interpTable.fileName_)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
Type Foam::interpolation2DTable<Type>::interpolateValue
(
const List<Tuple2<scalar, Type>>& data,
const scalar lookupValue
) const
{
label n = data.size();
scalar minLimit = data.first().first();
scalar maxLimit = data.last().first();
if (lookupValue < minLimit)
{
switch (boundsHandling_)
{
case interpolation2DTable::ERROR:
{
FatalErrorInFunction
<< "value (" << lookupValue << ") less than lower "
<< "bound (" << minLimit << ")" << nl
<< exit(FatalError);
break;
}
case interpolation2DTable::WARN:
{
WarningInFunction
<< "value (" << lookupValue << ") less than lower "
<< "bound (" << minLimit << ")" << nl
<< " Continuing with the first entry"
<< endl;
// fall-through to 'CLAMP'
[[fallthrough]];
}
case interpolation2DTable::CLAMP:
{
return data.first().second();
break;
}
}
}
else if (lookupValue >= maxLimit)
{
switch (boundsHandling_)
{
case interpolation2DTable::ERROR:
{
FatalErrorInFunction
<< "value (" << lookupValue << ") greater than upper "
<< "bound (" << maxLimit << ")" << nl
<< exit(FatalError);
break;
}
case interpolation2DTable::WARN:
{
WarningInFunction
<< "value (" << lookupValue << ") greater than upper "
<< "bound (" << maxLimit << ")" << nl
<< " Continuing with the last entry"
<< endl;
// fall-through to 'CLAMP'
[[fallthrough]];
}
case interpolation2DTable::CLAMP:
{
return data.last().second();
break;
}
}
}
// look for the correct range in X
label lo = 0;
label hi = 0;
for (label i = 0; i < n; ++i)
{
if (lookupValue >= data[i].first())
{
lo = hi = i;
}
else
{
hi = i;
break;
}
}
if (lo == hi)
{
return data[lo].second();
}
else
{
Type m =
(data[hi].second() - data[lo].second())
/(data[hi].first() - data[lo].first());
// normal interpolation
return data[lo].second() + m*(lookupValue - data[lo].first());
}
}
template<class Type>
template<class BinaryOp>
Foam::label Foam::interpolation2DTable<Type>::Xi
(
const BinaryOp& bop,
const scalar valueX,
const bool reverse
) const
{
const table& t = *this;
label limitI = 0;
if (reverse)
{
limitI = t.size() - 1;
}
if (bop(valueX, t[limitI].first()))
{
switch (boundsHandling_)
{
case interpolation2DTable::ERROR:
{
FatalErrorInFunction
<< "value (" << valueX << ") out of bounds"
<< exit(FatalError);
break;
}
case interpolation2DTable::WARN:
{
WarningInFunction
<< "value (" << valueX << ") out of bounds"
<< endl;
// fall-through to 'CLAMP'
[[fallthrough]];
}
case interpolation2DTable::CLAMP:
{
return limitI;
}
default:
{
FatalErrorInFunction
<< "Un-handled enumeration " << boundsHandling_
<< abort(FatalError);
}
}
}
label i = 0;
if (reverse)
{
label nX = t.size();
i = 0;
while ((i < nX) && (valueX > t[i].first()))
{
i++;
}
}
else
{
i = t.size() - 1;
while ((i > 0) && (valueX < t[i].first()))
{
i--;
}
}
return i;
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<class Type>
Type Foam::interpolation2DTable<Type>::operator()
(
const scalar valueX,
const scalar valueY
) const
{
// Considers all of the list in Y being equal
label nX = this->size();
const table& t = *this;
if (nX == 0)
{
WarningInFunction
<< "cannot interpolate a zero-sized table - returning zero" << endl;
return Zero;
}
else if (nX == 1)
{
// only 1 column (in X) - interpolate to find Y value
return interpolateValue(t.first().second(), valueY);
}
else
{
// have 2-D data, interpolate
// find low and high indices in the X range that bound valueX
label x0i = Xi(lessOp<scalar>(), valueX, false);
label x1i = Xi(greaterOp<scalar>(), valueX, true);
if (x0i == x1i)
{
return interpolateValue(t[x0i].second(), valueY);
}
else
{
Type y0(interpolateValue(t[x0i].second(), valueY));
Type y1(interpolateValue(t[x1i].second(), valueY));
// gradient in X
scalar x0 = t[x0i].first();
scalar x1 = t[x1i].first();
Type mX = (y1 - y0)/(x1 - x0);
// interpolate
return y0 + mX*(valueX - x0);
}
}
}
template<class Type>
Foam::word Foam::interpolation2DTable<Type>::boundsHandlingToWord
(
const boundsHandling& bound
) const
{
word enumName("warn");
switch (bound)
{
case interpolation2DTable::ERROR:
{
enumName = "error";
break;
}
case interpolation2DTable::WARN:
{
enumName = "warn";
break;
}
case interpolation2DTable::CLAMP:
{
enumName = "clamp";
break;
}
}
return enumName;
}
template<class Type>
typename Foam::interpolation2DTable<Type>::boundsHandling
Foam::interpolation2DTable<Type>::wordToBoundsHandling
(
const word& bound
) const
{
if (bound == "error")
{
return interpolation2DTable::ERROR;
}
else if (bound == "warn")
{
return interpolation2DTable::WARN;
}
else if (bound == "clamp")
{
return interpolation2DTable::CLAMP;
}
else
{
WarningInFunction
<< "bad outOfBounds specifier " << bound << " using 'warn'" << endl;
return interpolation2DTable::WARN;
}
}
template<class Type>
typename Foam::interpolation2DTable<Type>::boundsHandling
Foam::interpolation2DTable<Type>::outOfBounds
(
const boundsHandling& bound
)
{
boundsHandling prev = boundsHandling_;
boundsHandling_ = bound;
return prev;
}
template<class Type>
void Foam::interpolation2DTable<Type>::checkOrder() const
{
label n = this->size();
const table& t = *this;
scalar prevValue = t[0].first();
for (label i=1; i<n; ++i)
{
const scalar currValue = t[i].first();
// avoid duplicate values (divide-by-zero error)
if (currValue <= prevValue)
{
FatalErrorInFunction
<< "out-of-order value: "
<< currValue << " at index " << i << nl
<< exit(FatalError);
}
prevValue = currValue;
}
}
template<class Type>
void Foam::interpolation2DTable<Type>::write(Ostream& os) const
{
writeEntry(os, "file", fileName_);
writeEntry(os, "outOfBounds", boundsHandlingToWord(boundsHandling_));
reader_.write(os);
*this >> os;
}
// ************************************************************************* //

View File

@ -1,174 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2019 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/>.
Class
Foam::interpolation2DTable
Description
2D table interpolation. The data must be in ascending order in both
dimensions x and y.
SourceFiles
interpolation2DTable.C
\*---------------------------------------------------------------------------*/
#ifndef interpolation2DTable_H
#define interpolation2DTable_H
#include "List.H"
#include "Tuple2.H"
#include "TableReader.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class interpolation2DTable Declaration
\*---------------------------------------------------------------------------*/
template<class Type>
class interpolation2DTable
:
public List<Tuple2<scalar, List<Tuple2<scalar, Type>>>>
{
public:
// Public data types
//- Enumeration for handling out-of-bound values
enum boundsHandling
{
ERROR, //!< Exit with a FatalError
WARN, //!< Issue warning and clamp value (default)
CLAMP //!< Clamp value to the start/end value
};
//- Cconvenience typedef
typedef List<Tuple2<scalar, List<Tuple2<scalar, Type>>>> table;
private:
// Private Data
//- Enumeration for handling out-of-bound values
boundsHandling boundsHandling_;
//- File name
fileName fileName_;
//- The reader
autoPtr<TableReader<Type>> reader_;
// Private Member Functions
//- Return interpolated value in List
Type interpolateValue
(
const List<Tuple2<scalar, Type>>& data,
const scalar
) const;
//- Return an X index from the matrix
template<class BinaryOp>
label Xi
(
const BinaryOp& bop,
const scalar valueX,
const bool reverse
) const;
public:
// Constructors
//- Construct null
interpolation2DTable();
//- Construct from components
interpolation2DTable
(
const List<Tuple2<scalar, List<Tuple2<scalar, Type>>>>& values,
const boundsHandling bounds,
const fileName& fName
);
//- Construct given the name of the file containing the table of data
interpolation2DTable(const fileName& fName);
//- Construct by reading the fileName and boundsHandling from dictionary
interpolation2DTable(const dictionary& dict);
//- Construct copy
interpolation2DTable(const interpolation2DTable& interpTable);
// Member Functions
//- Return the out-of-bounds handling as a word
word boundsHandlingToWord(const boundsHandling& bound) const;
//- Return the out-of-bounds handling as an enumeration
boundsHandling wordToBoundsHandling(const word& bound) const;
//- Set the out-of-bounds handling from enum, return previous setting
boundsHandling outOfBounds(const boundsHandling& bound);
//- Check that list is monotonically increasing
// Exit with a FatalError if there is a problem
void checkOrder() const;
//- Write
void write(Ostream& os) const;
// Member Operators
//- Return an element of constant Tuple2<scalar, Type>
const List<Tuple2<scalar, Type>>& operator[](const label) const;
//- Return an interpolated value
Type operator()(const scalar, const scalar) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "interpolation2DTable.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -24,12 +24,10 @@ License
\*---------------------------------------------------------------------------*/
#include "effectivenessHeatExchangerSource.H"
#include "fvMesh.H"
#include "fvMatrix.H"
#include "addToRunTimeSelectionTable.H"
#include "basicThermo.H"
#include "coupledPolyPatch.H"
#include "surfaceInterpolate.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -61,7 +59,7 @@ void Foam::fv::effectivenessHeatExchangerSource::initialise()
label count = 0;
forAll(fZone, i)
{
label facei = fZone[i];
const label facei = fZone[i];
label faceId = -1;
label facePatchId = -1;
if (mesh_.isInternalFace(facei))
@ -126,7 +124,7 @@ void Foam::fv::effectivenessHeatExchangerSource::calculateTotalArea
area = 0;
forAll(faceId_, i)
{
label facei = faceId_[i];
const label facei = faceId_[i];
if (facePatchId_[i] != -1)
{
label patchi = facePatchId_[i];
@ -155,7 +153,7 @@ Foam::fv::effectivenessHeatExchangerSource::effectivenessHeatExchangerSource
secondaryMassFlowRate_(coeffs_.lookup<scalar>("secondaryMassFlowRate")),
secondaryInletT_(coeffs_.lookup<scalar>("secondaryInletT")),
primaryInletT_(coeffs_.lookup<scalar>("primaryInletT")),
eTable_(),
eTable_(Function2<scalar>::New("effectiveness", coeffs_)),
UName_(coeffs_.lookupOrDefault<word>("U", "U")),
TName_(coeffs_.lookupOrDefault<word>("T", "T")),
phiName_(coeffs_.lookupOrDefault<word>("phi", "phi")),
@ -185,8 +183,6 @@ Foam::fv::effectivenessHeatExchangerSource::effectivenessHeatExchangerSource
applied_.setSize(1, false);
eTable_.reset(new interpolation2DTable<scalar>(coeffs_));
initialise();
}
@ -231,8 +227,8 @@ void Foam::fv::effectivenessHeatExchangerSource::addSup
reduce(CpfMean, sumOp<scalar>());
reduce(totalphi, sumOp<scalar>());
scalar Qt =
eTable_()(mag(totalphi), secondaryMassFlowRate_)
const scalar Qt =
eTable_->value(mag(totalphi), secondaryMassFlowRate_)
*(secondaryInletT_ - primaryInletT_)
*(CpfMean/faceZoneArea_)*mag(totalphi);
@ -291,8 +287,8 @@ void Foam::fv::effectivenessHeatExchangerSource::addSup
Info<< indent << "Net mass flux [Kg/s] = " << totalphi << nl;
Info<< indent << "Total energy exchange [W] = " << Qt << nl;
Info<< indent << "Tref [K] = " << Tref << nl;
Info<< indent << "Efficiency : "
<< eTable_()(mag(totalphi), secondaryMassFlowRate_) << endl;
Info<< indent << "Effectiveness : "
<< eTable_->value(mag(totalphi), secondaryMassFlowRate_) << endl;
}
}

View File

@ -74,48 +74,18 @@ Usage
secondaryInletT 336;
primaryInletT 293;
faceZone facesZoneInletOriented;
outOfBounds clamp;
file "effTable";
effectiveness <function2>;
}
\endverbatim
The effectiveness table is described in terms of the primary and secondary
mass flow rates. For example, the table:
secondary MFR
| 0.1 0.2 0.3
-----+-----------------
0.02 | A B C
primary MFR 0.04 | D E F
0.06 | G H I
Is specified by the following:
(
0.02
(
(0.1 A)
(0.2 B)
(0.3 C)
),
0.04
(
(0.1 D)
(0.2 E)
(0.3 F)
),
0.06
(
(0.1 G)
(0.2 H)
(0.3 I)
)
);
The effectiveness Function2 is described in terms of the primary and
secondary mass flow rates and has the same units as the secondary mass flow
rate and kg/s for phi.
Note
- the table with name "file" should have the same units as the
secondary mass flow rate and kg/s for phi
- The effectiveness Function2 is described in terms of the primary and
secondary mass flow rates and has the same units as the secondary mass
flow rate and kg/s for phi.
- faceZone is the faces at the inlet of the cellzone, it needs to be
created with flip map flags. It is used to integrate the net mass flow
rate into the heat exchanger
@ -129,8 +99,7 @@ SourceFiles
#define effectivenessHeatExchangerSource_H
#include "cellSetOption.H"
#include "autoPtr.H"
#include "interpolation2DTable.H"
#include "Function2.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -161,9 +130,9 @@ protected:
//- Primary air temperature at the heat exchanger inlet [K]
scalar primaryInletT_;
//- 2D look up table efficiency = function of primary and secondary
// mass flow rates [kg/s]
autoPtr<interpolation2DTable<scalar>> eTable_;
//- 2D function for effectiveness [kg/s]
// function of primary and secondary mass flow rates [kg/s]
autoPtr<Function2<scalar>> eTable_;
//- Name of velocity field; default = U
word UName_;
@ -235,34 +204,26 @@ public:
// Member Functions
// Explicit and implicit source
//- Explicit and implicit source
virtual void addSup
(
fvMatrix<scalar>& eqn,
const label fieldi
) const
{
NotImplemented;
}
//- Scalar
virtual void addSup
(
fvMatrix<scalar>& eqn,
const label fieldi
) const
{
NotImplemented;
}
//- Explicit and implicit source for compressible equation
virtual void addSup
(
const volScalarField& rho,
fvMatrix<scalar>& eqn,
const label fieldi
) const;
// Explicit and implicit source for compressible equation
//- Scalar
virtual void addSup
(
const volScalarField& rho,
fvMatrix<scalar>& eqn,
const label fieldi
) const;
// IO
//- Read dictionary
virtual bool read(const dictionary& dict);
//- Read dictionary
virtual bool read(const dictionary& dict);
// Member Operators

View File

@ -34,7 +34,6 @@ Description
#define constantHeatTransfer_H
#include "interRegionHeatTransferModel.H"
#include "autoPtr.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -82,16 +81,13 @@ public:
virtual ~constantHeatTransfer();
// Public Functions
// Member Functions
//- Calculate the heat transfer coefficient
virtual void calculateHtc() const;
// IO
//- Read dictionary
virtual bool read(const dictionary& dict);
//- Read dictionary
virtual bool read(const dictionary& dict);
};

View File

@ -44,7 +44,6 @@ Description
#define variableHeatTransfer_H
#include "interRegionHeatTransferModel.H"
#include "autoPtr.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -103,16 +102,13 @@ public:
virtual ~variableHeatTransfer();
// Public Functions
// Member Functions
//- Calculate the heat transfer coefficient
virtual void calculateHtc() const;
// IO
//- Read dictionary
virtual bool read(const dictionary& dict) ;
//- Read dictionary
virtual bool read(const dictionary& dict) ;
};