42Foam::humidityTemperatureCoupledMixedFvPatchScalarField::massModeTypeNames_
44 { massTransferMode::mtConstantMass,
"constantMass" },
45 { massTransferMode::mtCondensation,
"condensation" },
46 { massTransferMode::mtEvaporation,
"evaporation" },
48 massTransferMode::mtCondensationAndEvaporation,
49 "condensationAndEvaporation"
56Foam::scalar Foam::humidityTemperatureCoupledMixedFvPatchScalarField::Sh
74Foam::humidityTemperatureCoupledMixedFvPatchScalarField::htcCondensation
81 if (Tsat > 295.15 && Tsat < 373.15)
83 return 51104 + 2044*(Tsat - 273.15);
93Foam::humidityTemperatureCoupledMixedFvPatchScalarField::thicknessField
95 const word& fieldName,
135 mixedFvPatchScalarField(
p, iF),
137 mode_(mtConstantMass),
141 muName_(
"thermo:mu"),
147 liquidDict_(nullptr),
148 mass_(patch().size(),
Zero),
150 myKDelta_(patch().size(),
Zero),
151 dmHfg_(patch().size(),
Zero),
152 mpCpTp_(patch().size(),
Zero),
156 cp_(patch().size(),
Zero),
157 thickness_(patch().size(),
Zero),
158 rho_(patch().size(),
Zero),
162 this->refValue() = 0.0;
163 this->refGrad() = 0.0;
164 this->valueFraction() = 1.0;
177 mixedFvPatchScalarField(psf,
p, iF, mapper),
182 rhoName_(psf.rhoName_),
183 muName_(psf.muName_),
184 TnbrName_(psf.TnbrName_),
185 qrNbrName_(psf.qrNbrName_),
186 qrName_(psf.qrName_),
187 specieName_(psf.specieName_),
188 liquid_(psf.liquid_.clone()),
189 liquidDict_(psf.liquidDict_),
190 mass_(psf.mass_, mapper),
192 myKDelta_(psf.myKDelta_, mapper),
193 dmHfg_(psf.dmHfg_, mapper),
194 mpCpTp_(psf.mpCpTp_, mapper),
198 cp_(psf.cp_, mapper),
199 thickness_(psf.thickness_, mapper),
200 rho_(psf.rho_, mapper),
201 thicknessLayers_(psf.thicknessLayers_),
202 kappaLayers_(psf.kappaLayers_)
214 mixedFvPatchScalarField(
p, iF),
216 mode_(mtCondensationAndEvaporation),
217 pName_(
dict.getOrDefault<
word>(
"p",
"p")),
218 UName_(
dict.getOrDefault<
word>(
"U",
"U")),
219 rhoName_(
dict.getOrDefault<
word>(
"rho",
"rho")),
220 muName_(
dict.getOrDefault<
word>(
"mu",
"thermo:mu")),
221 TnbrName_(
dict.getOrDefault<
word>(
"Tnbr",
"T")),
222 qrNbrName_(
dict.getOrDefault<
word>(
"qrNbr",
"none")),
223 qrName_(
dict.getOrDefault<
word>(
"qr",
"none")),
224 specieName_(
dict.getOrDefault<
word>(
"specie",
"none")),
227 mass_(patch().size(),
Zero),
229 myKDelta_(patch().size(),
Zero),
230 dmHfg_(patch().size(),
Zero),
231 mpCpTp_(patch().size(),
Zero),
235 cp_(patch().size(),
Zero),
236 thickness_(patch().size(),
Zero),
237 rho_(patch().size(),
Zero),
244 <<
"\n patch type '" <<
p.type()
245 <<
"' not type '" << mappedPatchBase::typeName <<
"'"
246 <<
"\n for patch " <<
p.name()
247 <<
" of field " << internalField().name()
248 <<
" in file " << internalField().objectPath()
259 if (
dict.readIfPresent(
"thicknessLayers", thicknessLayers_))
261 dict.readEntry(
"kappaLayers", kappaLayers_);
280 dict.readEntry(
"carrierMolWeight", Mcomp_);
281 dict.readEntry(
"L", L_);
282 dict.readEntry(
"Tvap", Tvap_);
283 liquidDict_ =
dict.subDict(
"liquid");
287 if (
dict.found(
"thickness"))
298 thickness_[i]*liquid_->rho(pf, Tp[i])*magSf[i];
308 <<
"Did not find mode " << mode_
309 <<
" on patch " <<
patch().name()
311 <<
"Please set 'mode' to one of "
312 << massModeTypeNames_.sortedToc()
319 if (this->readMixedEntries(
dict))
328 valueFraction() = 1.0;
337 const DimensionedField<scalar, volMesh>& iF
340 mixedFvPatchScalarField(psf, iF),
341 temperatureCoupledBase(patch(), psf),
345 rhoName_(psf.rhoName_),
346 muName_(psf.muName_),
347 TnbrName_(psf.TnbrName_),
348 qrNbrName_(psf.qrNbrName_),
349 qrName_(psf.qrName_),
350 specieName_(psf.specieName_),
351 liquid_(psf.liquid_.clone()),
352 liquidDict_(psf.liquidDict_),
355 myKDelta_(psf.myKDelta_),
357 mpCpTp_(psf.mpCpTp_),
362 thickness_(psf.thickness_),
364 thicknessLayers_(psf.thicknessLayers_),
365 kappaLayers_(psf.kappaLayers_)
376 mixedFvPatchScalarField::autoMap(m);
382 myKDelta_.autoMap(m);
386 thickness_.autoMap(m);
398 mixedFvPatchScalarField::rmap(ptf, addr);
409 mass_.rmap(tiptf.mass_, addr);
410 myKDelta_.rmap(tiptf.myKDelta_, addr);
411 dmHfg_.rmap(tiptf.dmHfg_, addr);
412 mpCpTp_.rmap(tiptf.mpCpTp_, addr);
413 cp_.rmap(tiptf.cp_, addr);
414 thickness_.rmap(tiptf.thickness_, addr);
415 rho_.rmap(tiptf.rho_, addr);
433 const label nbrPatchI = mpp.samplePolyPatch().index();
435 const polyMesh& nbrMesh = mpp.sampleMesh();
448 scalarField nbrIntFld(nbrField.patchInternalField());
449 mpp.distribute(nbrIntFld);
466 mpp.distribute(nbrK);
468 scalarField nrbDeltaCoeffs(nbrPatch.deltaCoeffs());
469 mpp.distribute(nrbDeltaCoeffs);
471 scalarField KDeltaNbr(nbrField.kappa(*
this)*nbrPatch.deltaCoeffs());
472 mpp.distribute(KDeltaNbr);
474 myKDelta_ =
K*
patch().deltaCoeffs();
476 if (thicknessLayers_.size() > 0)
478 myKDelta_ = 1.0/myKDelta_;
479 forAll(thicknessLayers_, iLayer)
481 myKDelta_ += thicknessLayers_[iLayer]/kappaLayers_[iLayer];
483 myKDelta_ = 1.0/myKDelta_;
496 if (mode_ != mtConstantMass)
534 const scalar Tf = Tp[faceI];
535 const scalar Tint = Tin[faceI];
537 const scalar pf =
pp[faceI];
539 const scalar muf = mup[faceI];
540 const scalar
rhof = rhop[faceI];
541 const scalar nuf = muf/
rhof;
542 const scalar pSat = liquid_->pv(pf, Tint);
543 const scalar Mv = liquid_->W();
544 const scalar TSat = liquid_->pvInvert(pSat);
545 const scalar
Re =
mag(
Uf)*L_/nuf;
547 cp[faceI] = liquid_->Cp(pf, Tf);
548 hfg[faceI] = liquid_->hl(pf, Tf);
551 const scalar invMwmean =
552 Yi[faceI]/Mv + (1.0 - Yi[faceI])/Mcomp_;
553 const scalar Xv = Yi[faceI]/invMwmean/Mv;
554 RH[faceI] =
min(Xv*pf/pSat, 1.0);
559 if (RH[faceI] > RHmin)
563 scalar TintDeg = Tint - 273;
565 b*(
log(RH[faceI]) + (
c*TintDeg)/(
b + TintDeg))
566 /(c -
log(RH[faceI]) - ((c*TintDeg)/(
b + TintDeg)))
575 mode_ == mtCondensation
576 || mode_ == mtCondensationAndEvaporation
580 htc[faceI] = htcCondensation(TSat,
Re)*nbrK[faceI]/L_;
583 1.0/((1.0/myKDelta_[faceI]) + (1.0/htc[faceI]));
586 const scalar q = (Tint - Tf)*htcTotal*magSf[faceI];
589 dm[faceI] = q/hfg[faceI]/magSf[faceI];
591 mass_[faceI] += q/hfg[faceI]*dt;
594 const scalar Dab = liquid_->D(pf, Tf);
596 -
min(dm[faceI]/Dab/
rhof, Yi[faceI]*myDelta[faceI]);
601 && mass_[faceI] > 0.0
603 mode_ == mtEvaporation
604 || mode_ == mtCondensationAndEvaporation
608 const scalar Dab = liquid_->D(pf, Tf);
610 const scalar Sc = nuf/Dab;
611 const scalar Sh = this->Sh(
Re, Sc);
613 const scalar Ys = Mv*pSat/(Mv*pSat + Mcomp_*(pf - pSat));
616 const scalar hm = Dab*Sh/L_;
618 const scalar Yinf =
max(Yi[faceI], 0.0);
621 dm[faceI] = -
rhof*hm*
max((Ys - Yinf), 0.0)/(1.0 - Ys);
624 Yvp[faceI] = -dm[faceI]/Dab/
rhof;
627 mass_[faceI] += dm[faceI]*magSf[faceI]*dt;
629 htc[faceI] = htcCondensation(TSat,
Re)*nbrK[faceI]/L_;
631 else if (Tf > Tdew[faceI] && Tf < Tvap_ && mass_[faceI] > 0.0)
633 htc[faceI] = htcCondensation(TSat,
Re)*nbrK[faceI]/L_;
635 else if (mass_[faceI] == 0.0)
640 liquidRho[faceI] = liquid_->rho(pf, Tf);
643 mass_ =
max(mass_, scalar(0));
648 const word fieldName(specieName_ +
"Thickness");
655 ).boundaryFieldRef()[
patch().index()];
658 pDelta = mass_/liquidRho/magSf;
661 myKDelta_ = 1.0/((1.0/myKDelta_) + (1.0/htc));
663 mpCpTp_ = mass_*
cp/dt/magSf;
676 ).boundaryFieldRef()[
patch().index()];
684 ).boundaryFieldRef()[
patch().index()];
691 mpCpTp_ = thickness_*rho_*cp_/dt;
700 mpCpTpNbr = nbrField.mpCpTp();
701 mpp.distribute(mpCpTpNbr);
703 dmHfgNbr = nbrField.dmHfg();
704 mpp.distribute(dmHfgNbr);
709 if (qrName_ !=
"none")
715 if (qrNbrName_ !=
"none")
718 mpp.distribute(qrNbr);
730 refValue() = (KDeltaNbr*nbrIntFld + mpCpdt*TpOld + dmHfg)/
alpha;
732 mixedFvPatchScalarField::updateCoeffs();
737 scalar QMass =
gSum(mass_);
738 scalar Qt =
gSum(myKDelta_*(Tp - Tin)*magSf);
739 scalar QtSolid =
gSum(KDeltaNbr*(Tp - nbrIntFld)*magSf);
744 <<
patch().name() <<
':'
745 << internalField().name() <<
" <- "
746 << nbrMesh.name() <<
':'
747 << nbrPatch.name() <<
':'
748 << internalField().name() <<
" :" <<
nl
749 <<
" Total mass flux [Kg/s] : " << Qdm <<
nl
750 <<
" Total mass on the wall [Kg] : " << QMass <<
nl
751 <<
" Total heat (>0 leaving the wall to the fluid) [W] : "
753 <<
" Total heat (>0 leaving the wall to the solid) [W] : "
755 <<
" wall temperature "
756 <<
" min:" <<
limits.min()
770 os.writeEntryIfDifferent<word>(
"p",
"p", pName_);
771 os.writeEntryIfDifferent<word>(
"U",
"U", UName_);
772 os.writeEntryIfDifferent<word>(
"rho",
"rho", rhoName_);
773 os.writeEntryIfDifferent<word>(
"mu",
"thermo:mu", muName_);
774 os.writeEntryIfDifferent<word>(
"Tnbr",
"T", TnbrName_);
775 os.writeEntryIfDifferent<word>(
"qrNbr",
"none", qrNbrName_);
776 os.writeEntryIfDifferent<word>(
"qr",
"none", qrName_);
780 os.writeEntry(
"mode", massModeTypeNames_[mode_]);
782 os.writeEntryIfDifferent<word>(
"specie",
"none", specieName_);
784 os.writeEntry(
"carrierMolWeight", Mcomp_);
786 os.writeEntry(
"L", L_);
787 os.writeEntry(
"Tvap", Tvap_);
788 os.writeEntry(
"fluid", fluid_);
789 mass_.writeEntry(
"mass",
os);
791 if (mode_ == mtConstantMass)
793 cp_.writeEntry(
"cp",
os);
794 rho_.writeEntry(
"rho",
os);
797 thickness_.writeEntry(
"thickness",
os);
800 liquidDict_.write(
os);
803 if (thicknessLayers_.size())
805 thicknessLayers_.writeEntry(
"thicknessLayers",
os);
806 kappaLayers_.writeEntry(
"kappaLayers",
os);
CGAL::Exact_predicates_exact_constructions_kernel K
Macros for easy insertion into run-time selection tables.
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
bool readIfPresent(const word &key, const dictionary &dict, EnumType &val, const bool warnOnly=false) const
Find an entry if present, and assign to T val.
@ REGISTER
Request registration (bool: true).
@ NO_READ
Nothing to be read.
@ MUST_READ
Reading required.
@ AUTO_WRITE
Automatically write from objectRegistry::writeObject().
Defines the attributes of an object for which implicit objectRegistry management is supported,...
const word & name() const noexcept
Return the object name.
A min/max value pair with additional methods. In addition to conveniently storing values,...
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
scalar deltaTValue() const noexcept
Return time step value.
static word timeName(const scalar t, const int precision=precision_)
Return a time name for the given scalar time value formatted with the given precision.
void size(const label n)
Older name for setAddressableSize.
Mixed boundary condition for temperature to be used at the coupling interface between fluid solid reg...
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
This boundary condition supplies a fixed gradient condition, such that the patch values are calculate...
virtual Field< Type > & gradient()
Return gradient at boundary.
Mesh data needed to do the Finite Volume discretisation.
const Time & time() const
Return the top-level database.
const word & name() const
Return reference to name.
A FieldMapper for finite-volume patch fields.
virtual tmp< Field< Type > > patchInternalField() const
Return internal field next to patch.
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
virtual const word & name() const
Return name.
const scalarField & deltaCoeffs() const
Return the face - cell distance coefficient except for coupled patches for which the cell-centre to c...
const GeometricField::Patch & lookupPatchField(const word &name) const
Lookup the named field from the local registry and return the patch field corresponding to this patch...
virtual void autoMap(const fvPatchFieldMapper &)
Map (and resize as needed) from self given a mapping object.
humidityTemperatureCoupledMixedFvPatchScalarField(const fvPatch &, const DimensionedField< scalar, volMesh > &)
Construct from patch and internal field.
virtual void write(Ostream &) const
Write.
virtual tmp< fvPatchField< scalar > > clone() const
Return a clone.
massTransferMode
Modes of mass transfer.
@ mtCondensationAndEvaporation
virtual void rmap(const fvPatchScalarField &, const labelList &)
Reverse map the given fvPatchField onto this fvPatchField.
const scalarField dmHfg() const
Return dmHfg.
virtual void updateCoeffs()
Update the coefficients associated with the patch field.
static autoPtr< liquidProperties > New(const word &name)
Return a pointer to a new liquidProperties created from name.
Determines a mapping between patch face centres and mesh cell or face centres and processors they're ...
const polyMesh & sampleMesh() const
Get the region mesh.
const polyPatch & samplePolyPatch() const
Get the patch on the region.
void distribute(List< Type > &lst) const
Wrapper around map/interpolate data distribution.
virtual void write(Ostream &) const
Write.
Type * getObjectPtr(const word &name, const bool recursive=false) const
Return non-const pointer to the object of the given Type, using a const-cast to have it behave like a...
label index() const noexcept
The index of this patch in the boundaryMesh.
Mesh consisting of general polyhedral cells.
Common functions used in temperature coupled boundaries.
virtual tmp< scalarField > alpha(const scalarField &Tp) const
Given patch temperature calculate corresponding alphaEff field.
virtual void autoMap(const fvPatchFieldMapper &)=0
Map (and resize as needed) from self given a mapping object.
void write(Ostream &os) const
Write.
virtual void rmap(const fvPatchField< scalar > &, const labelList &)=0
Reverse map the given fvPatchField onto this fvPatchField.
virtual tmp< scalarField > kappa(const scalarField &Tp) const
Given patch temperature calculate corresponding K field.
temperatureCoupledBase(const fvPatch &patch, const KMethodType method=KMethodType::mtFluidThermo)
Default construct from patch, using fluidThermo (default) or specified method.
A class for handling words, derived from Foam::string.
autoPtr< surfaceVectorField > Uf
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
OBJstream os(runTime.globalPath()/outputName)
#define makePatchTypeField(PatchTypeField, typePatchTypeField)
Define a concrete fvPatchField type and add to run-time tables Example, (fvPatchScalarField,...
surfaceScalarField rhof(fvc::interpolate(rho, "div(phi,rho)"))
const dimensionedScalar kappa
Coulomb constant: default SI units: [N.m2/C2].
const dimensionedScalar c
Speed of light in a vacuum.
Namespace for handling debugging switches.
const std::string patch
OpenFOAM patch number as a std::string.
Type gAverage(const FieldField< Field, Type > &f, const label comm)
The global arithmetic average of a FieldField.
Type & refCast(U &obj)
A dynamic_cast (for references) to Type reference.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Type gSum(const FieldField< Field, Type > &f)
GeometricField< vector, fvPatchField, volMesh > volVectorField
const dimensionSet dimless
Dimensionless.
List< label > labelList
A List of labels.
GeometricField< scalar, fvPatchField, volMesh > volScalarField
messageStream Info
Information stream (stdout output on master, null elsewhere).
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
dimensionedScalar log(const dimensionedScalar &ds)
Type gWeightedSum(const UList< scalar > &weights, const UList< Type > &fld, const label comm)
The global weighted sum (integral) of a field, using the mag() of the weights.
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
Ostream & endl(Ostream &os)
Add newline and flush stream.
dimensionedScalar sqrt(const dimensionedScalar &ds)
const Type * isA(const U &obj)
Attempt dynamic_cast to Type.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Field< vector > vectorField
Specialisation of Field<T> for vector.
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...
MinMax< Type > gMinMax(const FieldField< Field, Type > &f)
static constexpr const zero Zero
Global zero (0).
scalarField Re(const UList< complex > &cmplx)
Extract real component.
bool cp(const fileName &src, const fileName &dst, const bool followLink=true)
Copy the source to the destination (recursively if necessary).
dimensionedScalar cbrt(const dimensionedScalar &ds)
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
errorManipArg< error, int > exit(error &err, const int errNo=1)
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
fvPatchField< scalar > fvPatchScalarField
constexpr char nl
The newline '\n' character (0x0a).
const volScalarField & cp
#define forAll(list, i)
Loop across all elements in list.