ENH: Adding heatExchangerSource model as source
This commit is contained in:
@ -27,6 +27,7 @@ $(derivedSources)/rotorDiskSource/trimModel/trimModel/trimModel.C
|
||||
$(derivedSources)/rotorDiskSource/trimModel/trimModel/trimModelNew.C
|
||||
$(derivedSources)/rotorDiskSource/trimModel/fixed/fixedTrim.C
|
||||
$(derivedSources)/rotorDiskSource/trimModel/targetCoeff/targetCoeffTrim.C
|
||||
$(derivedSources)/heatExchangerSource/heatExchangerSource.C
|
||||
|
||||
interRegion = sources/interRegion
|
||||
$(interRegion)/interRegionHeatTransferModel/constantHeatTransfer/constantHeatTransfer.C
|
||||
@ -36,6 +37,7 @@ $(interRegion)/interRegionHeatTransferModel/variableHeatTransfer/variableHeatTra
|
||||
$(interRegion)/interRegionExplicitPorositySource/interRegionExplicitPorositySource.C
|
||||
|
||||
|
||||
|
||||
/* constraints */
|
||||
|
||||
generalConstraints=constraints/general
|
||||
|
||||
@ -0,0 +1,338 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2013-2013 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, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
\*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "heatExchangerSource.H"
|
||||
#include "fvMesh.H"
|
||||
#include "fvMatrix.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
#include "basicThermo.H"
|
||||
#include "coupledPolyPatch.H"
|
||||
#include "surfaceInterpolate.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace fv
|
||||
{
|
||||
defineTypeNameAndDebug(heatExchangerSource, 0);
|
||||
addToRunTimeSelectionTable
|
||||
(
|
||||
option,
|
||||
heatExchangerSource,
|
||||
dictionary
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::fv::heatExchangerSource::init()
|
||||
{
|
||||
const faceZone& fZone = mesh_.faceZones()[zoneID_];
|
||||
|
||||
faceId_.setSize(fZone.size());
|
||||
facePatchId_.setSize(fZone.size());
|
||||
faceSign_.setSize(fZone.size());
|
||||
|
||||
label count = 0;
|
||||
forAll(fZone, i)
|
||||
{
|
||||
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];
|
||||
if (isA<coupledPolyPatch>(pp))
|
||||
{
|
||||
if (refCast<const coupledPolyPatch>(pp).owner())
|
||||
{
|
||||
faceId = pp.whichFace(faceI);
|
||||
}
|
||||
else
|
||||
{
|
||||
faceId = -1;
|
||||
}
|
||||
}
|
||||
else if (!isA<emptyPolyPatch>(pp))
|
||||
{
|
||||
faceId = faceI - pp.start();
|
||||
}
|
||||
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);
|
||||
|
||||
calculateTotalArea(faceZoneArea_);
|
||||
}
|
||||
|
||||
|
||||
void Foam::fv::heatExchangerSource::addHeatSource
|
||||
(
|
||||
scalarField& heSource,
|
||||
const labelList& cells,
|
||||
const scalarField& Vcells,
|
||||
const vectorField& U,
|
||||
const scalar Qt,
|
||||
const scalarField& deltaTCells,
|
||||
const scalar totHeat
|
||||
) const
|
||||
{
|
||||
forAll(cells, i)
|
||||
{
|
||||
heSource[cells[i]] -=
|
||||
Qt*Vcells[cells[i]]*mag(U[cells[i]])*deltaTCells[i]/totHeat;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::fv::heatExchangerSource::calculateTotalArea(scalar& var)
|
||||
{
|
||||
var = 0;
|
||||
forAll(faceId_, i)
|
||||
{
|
||||
label faceI = faceId_[i];
|
||||
if (facePatchId_[i] != -1)
|
||||
{
|
||||
label patchI = facePatchId_[i];
|
||||
var += mesh_.magSf().boundaryField()[patchI][faceI];
|
||||
}
|
||||
else
|
||||
{
|
||||
var += mesh_.magSf()[faceI];
|
||||
}
|
||||
}
|
||||
reduce(var, sumOp<scalar>());
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::fv::heatExchangerSource::heatExchangerSource
|
||||
(
|
||||
const word& name,
|
||||
const word& modelType,
|
||||
const dictionary& dict,
|
||||
const fvMesh& mesh
|
||||
)
|
||||
:
|
||||
option(name, modelType, dict, mesh),
|
||||
secondaryMassFlowRate_(readScalar(coeffs_.lookup("secondaryMassFlowRate"))),
|
||||
secondaryInletT_(readScalar(coeffs_.lookup("secondaryInletT"))),
|
||||
primaryInletT_(readScalar(coeffs_.lookup("primaryInletT"))),
|
||||
eTable_(),
|
||||
UName_(coeffs_.lookupOrDefault<word>("UName", "U")),
|
||||
TName_(coeffs_.lookupOrDefault<word>("TName", "T")),
|
||||
phiName_(coeffs_.lookupOrDefault<word>("phiName", "phi")),
|
||||
faceZoneName_(coeffs_.lookup("faceZone")),
|
||||
zoneID_(mesh_.faceZones().findZoneID(faceZoneName_)),
|
||||
faceId_(),
|
||||
facePatchId_(),
|
||||
faceSign_(),
|
||||
faceZoneArea_(0)
|
||||
{
|
||||
|
||||
if (zoneID_ < 0)
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"heatExchangerSource::heatExchangerSource"
|
||||
"("
|
||||
" const word& name,"
|
||||
" const word& modelType,"
|
||||
" const dictionary& dict,"
|
||||
" const fvMesh& mesh"
|
||||
")"
|
||||
)
|
||||
<< type() << " " << this->name() << ": "
|
||||
<< " Unknown face zone name: " << faceZoneName_
|
||||
<< ". Valid face zones are: " << mesh_.faceZones().names()
|
||||
<< nl << exit(FatalError);
|
||||
}
|
||||
|
||||
coeffs_.lookup("fieldNames") >> fieldNames_;
|
||||
applied_.setSize(fieldNames_.size(), false);
|
||||
|
||||
eTable_.reset(new interpolation2DTable<scalar>(coeffs_));
|
||||
|
||||
init();
|
||||
|
||||
Info<< " - creating heatExchangerSource: "
|
||||
<< this->name() << endl;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::fv::heatExchangerSource::addSup
|
||||
(
|
||||
fvMatrix<scalar>& eqn,
|
||||
const label
|
||||
)
|
||||
{
|
||||
const basicThermo& thermo =
|
||||
mesh_.lookupObject<basicThermo>("thermophysicalProperties");
|
||||
|
||||
const surfaceScalarField Cpf = fvc::interpolate(thermo.Cp());
|
||||
|
||||
const surfaceScalarField& phi =
|
||||
mesh_.lookupObject<surfaceScalarField>(phiName_);
|
||||
|
||||
scalar totalphi = 0;
|
||||
scalar CpfMean = 0;
|
||||
forAll(faceId_, i)
|
||||
{
|
||||
label faceI = faceId_[i];
|
||||
if (facePatchId_[i] != -1)
|
||||
{
|
||||
label patchI = facePatchId_[i];
|
||||
totalphi += phi.boundaryField()[patchI][faceI]*faceSign_[i];
|
||||
|
||||
CpfMean +=
|
||||
Cpf.boundaryField()[patchI][faceI]
|
||||
* mesh_.magSf().boundaryField()[patchI][faceI];
|
||||
}
|
||||
else
|
||||
{
|
||||
totalphi += phi[faceI]*faceSign_[i];
|
||||
CpfMean += Cpf[faceI]*mesh_.magSf()[faceI];
|
||||
}
|
||||
}
|
||||
reduce(CpfMean, sumOp<scalar>());
|
||||
reduce(totalphi, sumOp<scalar>());
|
||||
|
||||
scalar Qt =
|
||||
eTable_()(mag(totalphi), secondaryMassFlowRate_)
|
||||
* (secondaryInletT_ - primaryInletT_)
|
||||
* (CpfMean/faceZoneArea_)*mag(totalphi);
|
||||
|
||||
const volScalarField& T = mesh_.lookupObject<volScalarField>(TName_);
|
||||
const scalarField TCells(T, cells_);
|
||||
scalar Tref = 0;
|
||||
if (Qt > 0)
|
||||
{
|
||||
Tref = max(TCells);
|
||||
reduce(Tref, maxOp<scalar>());
|
||||
}
|
||||
else
|
||||
{
|
||||
Tref = min(TCells);
|
||||
reduce(Tref, minOp<scalar>());
|
||||
}
|
||||
|
||||
scalarField deltaTCells(cells_.size(), 0);
|
||||
forAll(deltaTCells, i)
|
||||
{
|
||||
if (Qt > 0)
|
||||
{
|
||||
deltaTCells[i] = max(Tref - TCells[i], 0.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
deltaTCells[i] = max(TCells[i] - Tref, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
const volVectorField& U = mesh_.lookupObject<volVectorField>(UName_);
|
||||
const scalarField& cellsV = mesh_.V();
|
||||
scalar totHeat = 0;
|
||||
forAll(cells_, i)
|
||||
{
|
||||
totHeat += cellsV[cells_[i]]*mag(U[cells_[i]])*deltaTCells[i];
|
||||
}
|
||||
reduce(totHeat, sumOp<scalar>());
|
||||
|
||||
scalarField& heSource = eqn.source();
|
||||
|
||||
if (V() > VSMALL && mag(Qt) > VSMALL)
|
||||
{
|
||||
addHeatSource(heSource, cells_, cellsV, U, Qt, deltaTCells, totHeat);
|
||||
}
|
||||
|
||||
if (debug && Pstream::master())
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::fv::heatExchangerSource::writeData(Ostream& os) const
|
||||
{
|
||||
os << indent << name_ << endl;
|
||||
dict_.write(os);
|
||||
}
|
||||
|
||||
|
||||
bool Foam::fv::heatExchangerSource::read(const dictionary& dict)
|
||||
{
|
||||
if (option::read(dict))
|
||||
{
|
||||
coeffs_.lookup("secondaryMassFlowRate") >> secondaryMassFlowRate_;
|
||||
coeffs_.lookup("secondaryInletT") >> secondaryInletT_;
|
||||
coeffs_.lookup("primaryInletT") >> primaryInletT_;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,237 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2013-2013 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, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
Foam::fv::heatExchangerSource
|
||||
|
||||
Description
|
||||
Heat exchanger source model.
|
||||
The total heat exchange is given by:
|
||||
|
||||
Qt = e(phi, secondaryMassFlowRate)
|
||||
* (secondaryInletT - primaryInletT)
|
||||
* phi*Cp;
|
||||
|
||||
where:
|
||||
e(phi, secondaryMassFlowRate) is a effectivenes table in function of
|
||||
mass net flux coming imto the heat exchanger (phi) and
|
||||
secondaryMassFlowRate
|
||||
|
||||
Then the distribution inside the hear exchanger is given by:
|
||||
|
||||
Qcell = V*Ucell*(Tcell - Tref)/sum(V*Ucell*(Tcell - Tref));
|
||||
|
||||
where:
|
||||
Qcell is the source for cell
|
||||
V is the volume of the cell
|
||||
Ucell is the local cell velocity
|
||||
Tcell is the local call temperature
|
||||
Tref : min(T) or max(T) in the cell zone depending on the sign of Qt
|
||||
|
||||
Example :
|
||||
|
||||
heatExchangerSource1
|
||||
{
|
||||
type heatExchangerSource;
|
||||
active true;
|
||||
selectionMode cellZone;
|
||||
cellZone porosity;
|
||||
|
||||
heatExchangerSourceCoeffs
|
||||
{
|
||||
fieldNames (e);
|
||||
secondaryMassFlowRate 1.0;
|
||||
secondaryInletT 336;
|
||||
primaryInletT 293;
|
||||
faceZone facesZoneInletOriented;
|
||||
outOfBounds clamp;
|
||||
fileName "effTable";
|
||||
}
|
||||
}
|
||||
|
||||
Note:
|
||||
the table with name "fileName" should have the same units as
|
||||
secondaryMassFlowRate 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
|
||||
|
||||
|
||||
SourceFiles
|
||||
heatExchangerSource.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef heatExchangerSource_H
|
||||
#define heatExchangerSource_H
|
||||
|
||||
#include "fvOption.H"
|
||||
#include "autoPtr.H"
|
||||
#include "interpolation2DTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace fv
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class heatExchangerSource Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class heatExchangerSource
|
||||
:
|
||||
public option
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
// Protected data
|
||||
|
||||
//- Secondary flow mass rate [Kg/s]
|
||||
scalar secondaryMassFlowRate_;
|
||||
|
||||
//- Inlet secondary temperature [K]
|
||||
scalar secondaryInletT_;
|
||||
|
||||
//- Primary air temperature at the heat exchanger inlet [K]
|
||||
scalar primaryInletT_;
|
||||
|
||||
//- 2D look up table efficiency = F(total primary mass flow rate [Kg/s]
|
||||
//, secondary mass flow rate [Kg/s])
|
||||
autoPtr<interpolation2DTable<scalar> > eTable_;
|
||||
|
||||
//- Name of velocity field; default = U
|
||||
word UName_;
|
||||
|
||||
//- Name of temperature field; default = T
|
||||
word TName_;
|
||||
|
||||
//- Name of the flux
|
||||
word phiName_;
|
||||
|
||||
//- Name of the faceZone at the heat exchange inlet
|
||||
word faceZoneName_;
|
||||
|
||||
//- Id for the face zone
|
||||
label zoneID_;
|
||||
|
||||
//- Local list of face IDs
|
||||
labelList faceId_;
|
||||
|
||||
//- Local list of patch ID per face
|
||||
labelList facePatchId_;
|
||||
|
||||
//- List of +1/-1 representing face flip map
|
||||
// (1 use as is, -1 negate)
|
||||
labelList faceSign_;
|
||||
|
||||
//- Area of the face zone
|
||||
scalar faceZoneArea_;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
heatExchangerSource(const heatExchangerSource&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const heatExchangerSource&);
|
||||
|
||||
//- Add heat source
|
||||
void addHeatSource
|
||||
(
|
||||
scalarField& Tsource,
|
||||
const labelList& cells,
|
||||
const scalarField& V,
|
||||
const vectorField& U,
|
||||
const scalar Qt,
|
||||
const scalarField& deltaTref,
|
||||
const scalar totalHeat
|
||||
) const;
|
||||
|
||||
//- Init heat exchanger source model
|
||||
void init();
|
||||
|
||||
//- Calculate total area of faceZone accross procesors
|
||||
void calculateTotalArea(scalar& var);
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("heatExchangerSource");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from components
|
||||
heatExchangerSource
|
||||
(
|
||||
const word& name,
|
||||
const word& modelType,
|
||||
const dictionary& dict,
|
||||
const fvMesh& mesh
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~heatExchangerSource()
|
||||
{}
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
|
||||
// Public Functions
|
||||
|
||||
//- Source term to fvMatrix<scalar>
|
||||
virtual void addSup(fvMatrix<scalar>& eqn, const label fieldI);
|
||||
|
||||
|
||||
// I-O
|
||||
|
||||
//- Write data
|
||||
virtual void writeData(Ostream&) const;
|
||||
|
||||
//- Read dictionary
|
||||
virtual bool read(const dictionary& dict);
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace fv
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
Reference in New Issue
Block a user