35#include "surfaceInterpolate.H"
56void Foam::fv::effectivenessHeatExchangerSource::initialise()
63 <<
type() <<
" " << this->
name() <<
": "
64 <<
" Unknown face zone name: " << faceZoneName_
72 facePatchId_.
setSize(fZone.size());
73 faceSign_.
setSize(fZone.size());
78 const label facei = fZone[i];
80 label facePatchId = -1;
90 const auto* cpp = isA<coupledPolyPatch>(pp);
94 faceId = (cpp->owner() ? pp.whichFace(facei) : -1);
96 else if (!isA<emptyPolyPatch>(pp))
98 faceId = pp.whichFace(facei);
109 if (fZone.flipMap()[i])
111 faceSign_[
count] = -1;
115 faceSign_[
count] = 1;
118 facePatchId_[
count] = facePatchId;
128void Foam::fv::effectivenessHeatExchangerSource::writeFileHeader(Ostream&
os)
130 writeFile::writeHeader(
os,
"Effectiveness heat exchanger source");
131 writeFile::writeCommented(
os,
"Time");
132 writeFile::writeTabbed(
os,
"Net mass flux [kg/s]");
133 writeFile::writeTabbed(
os,
"Total heat exchange [W]");
134 writeFile::writeTabbed(
os,
"Secondary inlet T [K]");
135 writeFile::writeTabbed(
os,
"Tref [K]");
136 writeFile::writeTabbed(
os,
"Effectiveness");
140 writeFile::writeTabbed(
os,
"Secondary outlet T [K]");
152 const word& modelType,
158 writeFile(
mesh,
name, modelType, coeffs_),
159 userPrimaryInletT_(false),
160 targetQdotActive_(false),
172 targetQdotCalcInterval_(5),
173 secondaryMassFlowRate_(0),
177 targetQdotRelax_(0.5),
181 faceZoneName_(
"unknown-faceZone"),
201 writeFileHeader(
file());
222 scalar sumMagPhi = 0;
224 scalar primaryInletTfMean = 0;
227 const label facei = faceId_[i];
228 if (facePatchId_[i] != -1)
230 const label patchi = facePatchId_[i];
231 const scalar phii =
phi.boundaryField()[patchi][facei]*faceSign_[i];
232 const scalar magPhii =
mag(phii);
235 sumMagPhi += magPhii;
237 const scalar Cpfi = Cpf.boundaryField()[patchi][facei];
240 CpfMean += Cpfi*magPhii;
241 primaryInletTfMean += Tfi*magPhii;
245 const scalar phii =
phi[facei]*faceSign_[i];
246 const scalar magPhii =
mag(phii);
249 sumMagPhi += magPhii;
251 CpfMean += Cpf[facei]*magPhii;
252 primaryInletTfMean += Tf[facei]*magPhii;
258 CpfMean /= sumMagPhi + ROOTVSMALL;
260 scalar primaryInletT = primaryInletT_;
261 if (!userPrimaryInletT_)
264 primaryInletT = primaryInletTfMean/(sumMagPhi + ROOTVSMALL);
267 const scalar effectiveness = eTable_()(
mag(sumPhi), secondaryMassFlowRate_);
269 const scalar
alpha = effectiveness*CpfMean*
mag(sumPhi);
271 const scalar Qt =
alpha*(secondaryInletT_ - primaryInletT);
276 && (mesh_.time().timeIndex() % targetQdotCalcInterval_ == 0)
279 const scalar dT = (targetQdot_ - Qt)/(
alpha + ROOTVSMALL);
280 secondaryInletT_ += targetQdotRelax_*dT;
291 deltaTCells[i] =
max(Tref - TCells[i], scalar(0));
299 deltaTCells[i] =
max(TCells[i] - Tref, scalar(0));
306 scalar sumWeight = 0;
309 const label celli = cells_[i];
310 sumWeight += V[celli]*
mag(
U[celli])*deltaTCells[i];
314 if (this->V() > VSMALL &&
mag(Qt) > VSMALL)
320 const label celli = cells_[i];
322 Qt*V[celli]*
mag(
U[celli])*deltaTCells[i]
323 /(sumWeight + ROOTVSMALL);
329 <<
indent <<
"Net mass flux [kg/s] : " << sumPhi <<
nl
330 <<
indent <<
"Total heat exchange [W] : " << Qt <<
nl
331 <<
indent <<
"Secondary inlet T [K] : " << secondaryInletT_ <<
nl
332 <<
indent <<
"Tref [K] : " << Tref <<
nl
333 <<
indent <<
"Effectiveness : " << effectiveness
339 writeCurrentTime(
os);
343 <<
tab << secondaryInletT_
345 <<
tab << effectiveness;
350 const scalar secondaryCp = secondaryCpPtr_->value(secondaryInletT_);
351 const scalar secondaryOutletT =
352 Qt/(secondaryMassFlowRate_*secondaryCp) + secondaryInletT_;
355 <<
"Secondary outlet T [K] : " << secondaryOutletT
358 os <<
tab << secondaryOutletT;
374 coeffs_.readEntry(
"secondaryMassFlowRate", secondaryMassFlowRate_);
375 coeffs_.readEntry(
"secondaryInletT", secondaryInletT_);
377 if (coeffs_.readIfPresent(
"primaryInletT", primaryInletT_))
379 userPrimaryInletT_ =
true;
381 <<
"employing user-specified primary flow inlet temperature: "
382 << primaryInletT_ <<
endl;
387 <<
"employing flux-weighted primary flow inlet temperature"
391 if (coeffs_.readIfPresent(
"targetQdot", targetQdot_))
393 targetQdotActive_ =
true;
394 Info<<
indent <<
"employing target heat rejection of "
395 << targetQdot_ <<
nl;
397 coeffs_.readIfPresent
399 "targetQdotCalcInterval",
400 targetQdotCalcInterval_
403 Info<<
indent <<
"updating secondary inlet temperature every "
404 << targetQdotCalcInterval_ <<
" iterations" <<
nl;
406 coeffs_.readIfPresent(
"targetQdotRelax", targetQdotRelax_);
409 << targetQdotRelax_ <<
endl;
412 UName_ = coeffs_.getOrDefault<
word>(
"U",
"U");
413 TName_ = coeffs_.getOrDefault<
word>(
"T",
"T");
414 phiName_ = coeffs_.getOrDefault<
word>(
"phi",
"phi");
415 coeffs_.readEntry(
"faceZone", faceZoneName_);
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
Top level data entry class for use in dictionaries. Provides a mechanism to specify a variable as a c...
const Boundary & boundaryField() const
Return const-reference to the boundary field.
void setSize(const label n)
Alias for resize()
void resize(const label len)
Adjust allocated size of list.
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
virtual bool read()
Re-read model coefficients if they have changed.
label findZoneID(const word &zoneName) const
Find zone index by name, return -1 if not found.
wordList names() const
A list of the zone names.
Abstract base-class for fluid and solid thermodynamic properties.
static const word dictName
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
virtual OFstream & file()
Return access to the file (if only 1)
A special matrix type and solver, designed for finite volume solutions of scalar equations....
Field< Type > & source() noexcept
Mesh data needed to do the Finite Volume discretisation.
Intermediate abstract class for handling cell-set options for the derived fvOptions.
Heat exchanger source model for compressible flows, where the heat exchanger is modelled as an energy...
virtual bool read(const dictionary &dict)
Read dictionary.
virtual void addSup(fvMatrix< scalar > &eqn, const label fieldi)
Add explicit/implicit contribution to momentum equation.
Base abstract class for handling finite volume options (i.e. fvOption).
const word & name() const noexcept
Return const access to the source name.
const fvMesh & mesh_
Reference to the mesh database.
wordList fieldNames_
Field names to apply source to - populated by derived models.
dictionary coeffs_
Dictionary containing source coefficients.
void resetApplied()
Resize/reset applied flag list for all fieldNames_ entries.
2D table interpolation. The data must be in ascending order in both dimensions x and y.
const Type & lookupObject(const word &name, const bool recursive=false) const
label whichPatch(const label faceIndex) const
Return patch index for a given face label.
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
bool isInternalFace(const label faceIndex) const noexcept
Return true if given face label is internal to the mesh.
splitCell * master() const
Basic thermodynamics type based on the use of fitting functions for cp, h, s obtained from the templa...
A class for handling words, derived from Foam::string.
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
OBJstream os(runTime.globalPath()/outputName)
const labelIOList & zoneID
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of 'true' entries.
static tmp< GeometricField< Type, fvsPatchField, surfaceMesh > > interpolate(const GeometricField< Type, fvPatchField, volMesh > &tvf, const surfaceScalarField &faceFlux, Istream &schemeData)
Interpolate field onto faces using scheme given by Istream.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
messageStream Info
Information stream (stdout output on master, null elsewhere)
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Ostream & incrIndent(Ostream &os)
Increment the indent level.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Ostream & indent(Ostream &os)
Indent stream.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
void reduce(const List< UPstream::commsStruct > &comms, T &value, const BinaryOp &bop, const int tag, const label comm)
static constexpr const zero Zero
Global zero (0)
Type gMin(const FieldField< Field, Type > &f)
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Ostream & decrIndent(Ostream &os)
Decrement the indent level.
Type gMax(const FieldField< Field, Type > &f)
constexpr char nl
The newline '\n' character (0x0a)
constexpr char tab
The tab '\t' character(0x09)
#define forAll(list, i)
Loop across all elements in list.