ENH: Adding heatExchangerSource model as source

This commit is contained in:
sergio
2013-02-15 10:17:50 +00:00
parent 373a13734c
commit 8726ebac89
3 changed files with 577 additions and 0 deletions

View File

@ -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

View File

@ -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;
}
}
// ************************************************************************* //

View File

@ -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
// ************************************************************************* //