diff --git a/src/fvOptions/Make/files b/src/fvOptions/Make/files index 7ede3766061a3b546f3f0d6c0bcfbbb92b59c5e3..d481c16016bf51730d76147a469140b52aae6389 100644 --- a/src/fvOptions/Make/files +++ b/src/fvOptions/Make/files @@ -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 diff --git a/src/fvOptions/sources/derived/effectivenessHeatExchangerSource/effectivenessHeatExchangerSource.C b/src/fvOptions/sources/derived/heatExchangerSource/heatExchangerModels/effectivenessTable/effectivenessTable.C similarity index 51% rename from src/fvOptions/sources/derived/effectivenessHeatExchangerSource/effectivenessHeatExchangerSource.C rename to src/fvOptions/sources/derived/heatExchangerSource/heatExchangerModels/effectivenessTable/effectivenessTable.C index ae487be30a1bcebbc082e661025d15a9313edc77..3d4ed5576074a954cf493848c26ff3637a218a7a 100644 --- a/src/fvOptions/sources/derived/effectivenessHeatExchangerSource/effectivenessHeatExchangerSource.C +++ b/src/fvOptions/sources/derived/heatExchangerSource/heatExchangerModels/effectivenessTable/effectivenessTable.C @@ -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 * * * * * * * * * * * // - -void Foam::fv::effectivenessHeatExchangerSource::initialise() -{ - 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); -} - +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // -void Foam::fv::effectivenessHeatExchangerSource::writeFileHeader(Ostream& os) +void Foam::heatExchangerModels::effectivenessTable::writeFileHeader +( + Ostream& os +) const { - 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); + writeFileHeader(file()); +} - fieldNames_.resize(1, thermo.he().name()); - fv::option::resetApplied(); +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // +void Foam::heatExchangerModels::effectivenessTable::initialise() +{ eTable_.reset(new interpolation2DTable<scalar>(coeffs_)); - initialise(); - - writeFileHeader(file()); + heatExchangerModel::initialise(); } -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - -void Foam::fv::effectivenessHeatExchangerSource::addSup +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,123 +191,76 @@ 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(); - - forAll(cells_, i) - { - const label celli = cells_[i]; - heSource[celli] -= - Qt*V[celli]*mag(U[celli])*deltaTCells[i] - /(sumWeight + ROOTVSMALL); - } - } - - 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; - - if (Pstream::master()) - { - Ostream& os = file(); - writeCurrentTime(os); - - os << tab << sumPhi - << tab << Qt - << tab << secondaryInletT_ - << 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_; - - Log << nl << incrIndent << indent - << "Secondary outlet T [K] : " << secondaryOutletT - << decrIndent; - - os << tab << secondaryOutletT; - } - os << endl; - } - - Info<< nl << endl; + return Qt_*deltaTCells/(sumWeight + ROOTVSMALL); } -bool Foam::fv::effectivenessHeatExchangerSource::read(const dictionary& dict) +bool Foam::heatExchangerModels::effectivenessTable::read(const dictionary& dict) { - if (!(fv::cellSetOption::read(dict) && writeFile::read(dict))) + if (!writeFile::read(dict)) { return false; } + Info<< incrIndent << indent << "- using model: " << type() << endl; + 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: " + + Info<< indent + << "- using user-specified primary flow inlet temperature: " << primaryInletT_ << endl; } else { - Info<< type() << " " << this->name() << ": " << indent << nl - << "employing flux-weighted primary flow inlet temperature" + Info<< indent + << "- using flux-weighted primary flow inlet temperature" << endl; } if (coeffs_.readIfPresent("targetQdot", targetQdot_)) { targetQdotActive_ = true; - Info<< indent << "employing target heat rejection of " - << targetQdot_ << nl; + + Info<< indent << "- using target heat rejection: " << targetQdot_ << nl; coeffs_.readIfPresent ( @@ -400,12 +268,12 @@ bool Foam::fv::effectivenessHeatExchangerSource::read(const dictionary& dict) targetQdotCalcInterval_ ); - Info<< indent << "updating secondary inlet temperature every " + Info<< indent << "- updating secondary inlet temperature every " << targetQdotCalcInterval_ << " iterations" << nl; coeffs_.readIfPresent("targetQdotRelax", targetQdotRelax_); - Info<< indent << "temperature relaxation: " + Info<< indent << "- temperature relaxation: " << targetQdotRelax_ << endl; } @@ -414,8 +282,61 @@ bool Foam::fv::effectivenessHeatExchangerSource::read(const dictionary& dict) 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_ + << tab << secondaryInletT_ + << 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_; + + if (log) + { + Info << nl << incrIndent << indent + << "Secondary outlet T [K] : " << secondaryOutletT + << decrIndent; + } + + os << tab << secondaryOutletT; + } + os << endl; + } + + Info<< nl << endl; +} + + // ************************************************************************* // diff --git a/src/fvOptions/sources/derived/effectivenessHeatExchangerSource/effectivenessHeatExchangerSource.H b/src/fvOptions/sources/derived/heatExchangerSource/heatExchangerModels/effectivenessTable/effectivenessTable.H similarity index 63% rename from src/fvOptions/sources/derived/effectivenessHeatExchangerSource/effectivenessHeatExchangerSource.H rename to src/fvOptions/sources/derived/heatExchangerSource/heatExchangerModels/effectivenessTable/effectivenessTable.H index b443e751e657431005258ed5d617e7e3f0f8f8d1..476713f8e2f8b399a236cda89203051492506d09 100644 --- a/src/fvOptions/sources/derived/effectivenessHeatExchangerSource/effectivenessHeatExchangerSource.H +++ b/src/fvOptions/sources/derived/heatExchangerSource/heatExchangerModels/effectivenessTable/effectivenessTable.H @@ -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_; - - //- Name of operand temperature field - word TName_; + //- Net mass flux [kg/s] + scalar sumPhi_; - //- Name of operand flux field - word phiName_; + //- Total heat exchange [W] + scalar Qt_; - //- Name of the faceZone at the heat exchanger inlet - word faceZoneName_; + //- Reference temperature [K] + scalar Tref_; - //- 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; - } - - //- Add explicit/implicit contribution - //- to compressible momentum equation - virtual void addSup - ( - const volScalarField& rho, - fvMatrix<scalar>& eqn, - const label fieldi - ); + // 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 - // I-O + //- Read top-level dictionary + virtual bool read(const dictionary& dict); - //- Read 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 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/fvOptions/sources/derived/heatExchangerSource/heatExchangerModels/heatExchangerModel/heatExchangerModel.C b/src/fvOptions/sources/derived/heatExchangerSource/heatExchangerModels/heatExchangerModel/heatExchangerModel.C new file mode 100644 index 0000000000000000000000000000000000000000..9034a02b9182961c883d6f00fd0ad78c4ba1070c --- /dev/null +++ b/src/fvOptions/sources/derived/heatExchangerSource/heatExchangerModels/heatExchangerModel/heatExchangerModel.C @@ -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); +} + + +// ************************************************************************* // diff --git a/src/fvOptions/sources/derived/heatExchangerSource/heatExchangerModels/heatExchangerModel/heatExchangerModel.H b/src/fvOptions/sources/derived/heatExchangerSource/heatExchangerModels/heatExchangerModel/heatExchangerModel.H new file mode 100644 index 0000000000000000000000000000000000000000..39e6ebdb590ec746704f0959e6c31d3375ad5de4 --- /dev/null +++ b/src/fvOptions/sources/derived/heatExchangerSource/heatExchangerModels/heatExchangerModel/heatExchangerModel.H @@ -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 + +// ************************************************************************* // diff --git a/src/fvOptions/sources/derived/heatExchangerSource/heatExchangerModels/heatExchangerModel/heatExchangerModelNew.C b/src/fvOptions/sources/derived/heatExchangerSource/heatExchangerModels/heatExchangerModel/heatExchangerModelNew.C new file mode 100644 index 0000000000000000000000000000000000000000..90acf6074e32e88570c048d0c7e3d37f70e8889a --- /dev/null +++ b/src/fvOptions/sources/derived/heatExchangerSource/heatExchangerModels/heatExchangerModel/heatExchangerModelNew.C @@ -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)); +} + + +// ************************************************************************* // diff --git a/src/fvOptions/sources/derived/heatExchangerSource/heatExchangerModels/referenceTemperature/referenceTemperature.C b/src/fvOptions/sources/derived/heatExchangerSource/heatExchangerModels/referenceTemperature/referenceTemperature.C new file mode 100644 index 0000000000000000000000000000000000000000..c022de3f21213646277002f3165c7a76d4497b58 --- /dev/null +++ b/src/fvOptions/sources/derived/heatExchangerSource/heatExchangerModels/referenceTemperature/referenceTemperature.C @@ -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; +} + + +// ************************************************************************* // diff --git a/src/fvOptions/sources/derived/heatExchangerSource/heatExchangerModels/referenceTemperature/referenceTemperature.H b/src/fvOptions/sources/derived/heatExchangerSource/heatExchangerModels/referenceTemperature/referenceTemperature.H new file mode 100644 index 0000000000000000000000000000000000000000..123f088140f967afb8f367e666a4cac5dc57f63b --- /dev/null +++ b/src/fvOptions/sources/derived/heatExchangerSource/heatExchangerModels/referenceTemperature/referenceTemperature.H @@ -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 + +// ************************************************************************* // diff --git a/src/fvOptions/sources/derived/heatExchangerSource/heatExchangerSource.C b/src/fvOptions/sources/derived/heatExchangerSource/heatExchangerSource.C new file mode 100644 index 0000000000000000000000000000000000000000..2a3cdb3dca526d63972e9dd4b5eca3e7097d3d32 --- /dev/null +++ b/src/fvOptions/sources/derived/heatExchangerSource/heatExchangerSource.C @@ -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; +} + + +// ************************************************************************* // diff --git a/src/fvOptions/sources/derived/heatExchangerSource/heatExchangerSource.H b/src/fvOptions/sources/derived/heatExchangerSource/heatExchangerSource.H new file mode 100644 index 0000000000000000000000000000000000000000..cf3d7d0c54e54cff8c9f8c792d808ea1b4f6b495 --- /dev/null +++ b/src/fvOptions/sources/derived/heatExchangerSource/heatExchangerSource.H @@ -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 + +// ************************************************************************* //