diff --git a/src/thermophysicalModels/reactionThermo/Make/files b/src/thermophysicalModels/reactionThermo/Make/files index f72e0ff4a6..1778902590 100644 --- a/src/thermophysicalModels/reactionThermo/Make/files +++ b/src/thermophysicalModels/reactionThermo/Make/files @@ -19,6 +19,7 @@ derivedFvPatchFields/fixedUnburntEnthalpy/fixedUnburntEnthalpyFvPatchScalarField derivedFvPatchFields/gradientUnburntEnthalpy/gradientUnburntEnthalpyFvPatchScalarField.C derivedFvPatchFields/mixedUnburntEnthalpy/mixedUnburntEnthalpyFvPatchScalarField.C derivedFvPatchFields/speciesSorption/speciesSorptionFvPatchScalarField.C +derivedFvPatchFields/enthalpySorption/enthalpySorptionFvPatchScalarField.C derivedFvPatchFields/boundarySourcePatch/boundarySourcePatch.C functionObjects/moleFractions/moleFractionsFunctionObjects.C diff --git a/src/thermophysicalModels/reactionThermo/derivedFvPatchFields/enthalpySorption/enthalpySorptionFvPatchScalarField.C b/src/thermophysicalModels/reactionThermo/derivedFvPatchFields/enthalpySorption/enthalpySorptionFvPatchScalarField.C new file mode 100644 index 0000000000..694dc96d98 --- /dev/null +++ b/src/thermophysicalModels/reactionThermo/derivedFvPatchFields/enthalpySorption/enthalpySorptionFvPatchScalarField.C @@ -0,0 +1,350 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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 . + +\*---------------------------------------------------------------------------*/ + +#include "enthalpySorptionFvPatchScalarField.H" +#include "addToRunTimeSelectionTable.H" +#include "fvPatchFieldMapper.H" +#include "volFields.H" +#include "rhoReactionThermo.H" +#include "speciesSorptionFvPatchScalarField.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +const Foam::Enum +< + Foam::enthalpySorptionFvPatchScalarField::enthalpyModelType +> +Foam::enthalpySorptionFvPatchScalarField::enthalpyModelTypeNames +({ + { enthalpyModelType::estimated, "estimated" }, + { enthalpyModelType::calculated, "calculated" } +}); + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::enthalpySorptionFvPatchScalarField::enthalpySorptionFvPatchScalarField +( + const fvPatch& p, + const DimensionedField& iF +) +: + zeroGradientFvPatchScalarField(p, iF), + enthalpyModel_(enthalpyModelType::estimated), + includeHs_(false), + enthalpyMassLoadPtr_(nullptr), + C_(0), + Hvap_(0), + speciesName_("none"), + pName_("p"), + TName_("T"), + dhdt_(p.size(), 0) +{} + + +Foam::enthalpySorptionFvPatchScalarField::enthalpySorptionFvPatchScalarField +( + const fvPatch& p, + const DimensionedField& iF, + const dictionary& dict +) +: + zeroGradientFvPatchScalarField(p, iF, dict), + enthalpyModel_(enthalpyModelTypeNames.get("enthalpyModel", dict)), + includeHs_(dict.getOrDefault("includeHs", true)), + enthalpyMassLoadPtr_(nullptr), + C_(dict.getCheckOrDefault("C", 0, scalarMinMax::ge(0))), + Hvap_(dict.getCheckOrDefault("Hvap", 0, scalarMinMax::ge(0))), + speciesName_(dict.get("species")), + pName_(dict.getOrDefault("p", "p")), + TName_(dict.getOrDefault("T", "T")), + dhdt_ + ( + dict.found("dhdt") + ? scalarField("dhdt", dict, p.size()) + : scalarField(p.size(), 0) + ) +{ + switch (enthalpyModel_) + { + case enthalpyModelType::calculated: + { + enthalpyMassLoadPtr_ = + Function1::New("enthalpyTable", dict); + break; + } + case enthalpyModelType::estimated: + { + break; + } + } + + if (dict.found("value")) + { + fvPatchScalarField::operator= + ( + scalarField("value", dict, p.size()) + ); + } + else + { + fvPatchField::operator=(Zero); + } +} + + +Foam::enthalpySorptionFvPatchScalarField::enthalpySorptionFvPatchScalarField +( + const enthalpySorptionFvPatchScalarField& ptf, + const fvPatch& p, + const DimensionedField& iF, + const fvPatchFieldMapper& mapper +) +: + zeroGradientFvPatchScalarField(ptf, p, iF, mapper), + enthalpyModel_(ptf.enthalpyModel_), + includeHs_(ptf.includeHs_), + enthalpyMassLoadPtr_(ptf.enthalpyMassLoadPtr_.clone()), + C_(ptf.C_), + Hvap_(ptf.Hvap_), + speciesName_(ptf.speciesName_), + pName_(ptf.pName_), + TName_(ptf.TName_), + dhdt_(ptf.dhdt_, mapper) +{} + + +Foam::enthalpySorptionFvPatchScalarField::enthalpySorptionFvPatchScalarField +( + const enthalpySorptionFvPatchScalarField& ptf +) +: + zeroGradientFvPatchScalarField(ptf), + enthalpyModel_(ptf.enthalpyModel_), + includeHs_(ptf.includeHs_), + enthalpyMassLoadPtr_(ptf.enthalpyMassLoadPtr_.clone()), + C_(ptf.C_), + Hvap_(ptf.Hvap_), + speciesName_(ptf.speciesName_), + pName_(ptf.pName_), + TName_(ptf.TName_), + dhdt_(ptf.dhdt_) +{} + + +Foam::enthalpySorptionFvPatchScalarField::enthalpySorptionFvPatchScalarField +( + const enthalpySorptionFvPatchScalarField& ptf, + const DimensionedField& iF +) +: + zeroGradientFvPatchScalarField(ptf, iF), + enthalpyModel_(ptf.enthalpyModel_), + includeHs_(ptf.includeHs_), + enthalpyMassLoadPtr_(ptf.enthalpyMassLoadPtr_.clone()), + C_(ptf.C_), + Hvap_(ptf.Hvap_), + speciesName_(ptf.speciesName_), + pName_(ptf.pName_), + TName_(ptf.TName_), + dhdt_(ptf.dhdt_) +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::enthalpySorptionFvPatchScalarField::autoMap +( + const fvPatchFieldMapper& m +) +{ + zeroGradientFvPatchScalarField::autoMap(m); + + dhdt_.autoMap(m); +} + + +void Foam::enthalpySorptionFvPatchScalarField::rmap +( + const fvPatchScalarField& ptf, + const labelList& addr +) +{ + zeroGradientFvPatchScalarField::rmap(ptf, addr); + + const auto& tiptf = refCast(ptf); + + dhdt_.rmap(tiptf.dhdt_, addr); +} + + +Foam::tmp Foam::enthalpySorptionFvPatchScalarField:: +patchSource() const +{ + const auto& Yp = + refCast + ( + patch().lookupPatchField + ( + speciesName_ + ) + ); + + // mass rate [kg/sec/m3] + tmp tmassb = Yp.patchSource(); + const scalarField& massb = tmassb(); + + // The moles absorbed by the solid + // dhdt[J/kg] * kg/sec/m3 = [J/m3/s] + scalarField dhdt(dhdt_*massb); + + if (includeHs_) + { + const fvPatchField& pp = + patch().lookupPatchField(pName_); + + const fvPatchField& Tp = + patch().lookupPatchField(TName_); + + const auto& thermo = db().lookupObject + ( + basicThermo::dictName + ); + + const basicSpecieMixture& composition = thermo.composition(); + + const label speicesId = + thermo.composition().species()[speciesName_]; + + scalarField hsp(this->patch().size(), 0); + + forAll(pp, facei) + { + hsp[facei] = composition.Hs(speicesId, pp[facei], Tp[facei]); + } + + dhdt += hsp*massb; + } + + if (debug) + { + Info<< " Patch enthalpy rate min/max [J/m3/sec]: " + << gMin(dhdt) << " - " << gMax(dhdt) << endl; + } + + return tmp::New(dhdt); +} + + +void Foam::enthalpySorptionFvPatchScalarField::updateCoeffs() +{ + if (updated()) + { + return; + } + + const auto& Yp = + refCast + ( + patch().lookupPatchField + ( + speciesName_ + ) + ); + + switch (enthalpyModel_) + { + case enthalpyModelType::estimated: + { + dhdt_ = -C_*Hvap_; + break; + } + case enthalpyModelType::calculated: + { + // mass [mol/kg] + tmp tmassb = Yp.mass(); + const scalarField& massb = tmassb.ref(); + + forAll(massb, facei) + { + const scalar mfacei = massb[facei]; + + dhdt_[facei] = enthalpyMassLoadPtr_->value(mfacei); + } + break; + } + default: + break; + } + + if (debug) + { + Info<< " Enthalpy change min/max [J/kg]: " + << gMin(dhdt_) << " - " << gMax(dhdt_) << endl; + } + + zeroGradientFvPatchScalarField::updateCoeffs(); +} + + +void Foam::enthalpySorptionFvPatchScalarField::write(Ostream& os) const +{ + fvPatchScalarField::write(os); + + os.writeEntry("enthalpyModel", enthalpyModelTypeNames[enthalpyModel_]); + + if (enthalpyMassLoadPtr_) + { + enthalpyMassLoadPtr_->writeData(os); + } + + os.writeEntry("species", speciesName_); + + os.writeEntryIfDifferent("includeHs", true, includeHs_); + os.writeEntryIfDifferent("C", scalar(0), C_); + os.writeEntryIfDifferent("Hvap", scalar(0), Hvap_); + os.writeEntryIfDifferent("p", "p", pName_); + os.writeEntryIfDifferent("T", "T", TName_); + + dhdt_.writeEntry("dhdt", os); + + writeEntry("value", os); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + makePatchTypeField + ( + fvPatchScalarField, + enthalpySorptionFvPatchScalarField + ); +} + +// ************************************************************************* // diff --git a/src/thermophysicalModels/reactionThermo/derivedFvPatchFields/enthalpySorption/enthalpySorptionFvPatchScalarField.H b/src/thermophysicalModels/reactionThermo/derivedFvPatchFields/enthalpySorption/enthalpySorptionFvPatchScalarField.H new file mode 100644 index 0000000000..f232c79c71 --- /dev/null +++ b/src/thermophysicalModels/reactionThermo/derivedFvPatchFields/enthalpySorption/enthalpySorptionFvPatchScalarField.H @@ -0,0 +1,284 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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 . + +Class + Foam::enthalpySorptionFvPatchScalarField + +Group + grpGenericBoundaryConditions + +Description + This is a temperature boundary condition which works + in conjunction with the \c speciesSorption condition for species. + + This boundary condition substracts or adds enthalpy associated with the + adsorption provided by the \c speciesSorption condition. + + It can handle two enthalpy models: + + 1) Estimate + 2) Calculated + + On top of this, the enthalpy associated with the sensible enthalpy + corresponding with the species transport can be added using \c includeHs. + +Usage + Example of the boundary condition specification: + \verbatim + + { + // Mandatory entries + type enthalpySorption; + enthalpyModel ; + species ; + + // Conditional mandatory entries + + // when enthalpyModel == calculated + enthalpyTable > + + // enthalpyTable + // { + // type table; + // values ((0 0)(1 50)); + // } + + // Optional entries + includeHs ; + C ; + Hvap ; + dhdt ; + p ; + T ; + } + \endverbatim + + where the entries mean: + \table + Property | Description | Type | Reqd | Deflt + type | Type name: enthalpySorption | word | yes | - + enthalpyModel | Adsorption enthalpy model | word | yes | - + species | Name of associated species | word | yes | - + enthalpyTable | Calculated enthalpy model table | Function1\ | no | - + includeHs | Include sensible enthalpy | bool | no | true + C | Estimate enthalpy model constant | scalar | no | 0 + Hvap | Evaporation heat for species | scalar | no | 0 + p | Name of operand pressure field | word | no | p + T | Name of operand temperature field | word | no | T + dhdt | Enthalpy change on cells next to patch [J/kg] | scalarField | no | Zero + \endtable + + Options for the \c enthalpyModel entry: + \verbatim + estimated | Enthalpy is estimated + calculated | Enthalpy is calculated based on enthalpyTable + \endverbatim + + The inherited entries are elaborated in: + - \link zeroGradientFvPatchFields.H \endlink + - \link Function1.H \endlink + +SourceFiles + enthalpySorptionFvPatchScalarField.C + +\*---------------------------------------------------------------------------*/ + +#ifndef Foam_enthalpySorptionFvPatchScalarField_H +#define Foam_enthalpySorptionFvPatchScalarField_H + +#include "boundarySourcePatch.H" +#include "zeroGradientFvPatchFields.H" +#include "Function1.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class enthalpySorptionFvPatchScalarField Declaration +\*---------------------------------------------------------------------------*/ + +class enthalpySorptionFvPatchScalarField +: + public zeroGradientFvPatchField, + public boundarySourcePatch +{ + // Private Enumeration + + //- Options for the enthalpy model + enum enthalpyModelType : char + { + estimated, + calculated + }; + + //- Names for enthalpyModelType + static const Enum enthalpyModelTypeNames; + + + // Private Data + + //- Enthalpy model + enum enthalpyModelType enthalpyModel_; + + //- Include sensible enthalpy of the species + bool includeHs_; + + //- Load enthalpy table for calculated model + autoPtr> enthalpyMassLoadPtr_; + + //- Estimated enthalpy model constant + scalar C_; + + //- Heat of evaporation of species + scalar Hvap_; + + //- Name of operand species field + word speciesName_; + + //- Name of operand pressure field + word pName_; + + //- Name of operand temperature field + word TName_; + + //- Enthalpy change on cells next to patch [J/kg] + scalarField dhdt_; + + +public: + + //- Runtime type information + TypeName("enthalpySorption"); + + + // Constructors + + //- Construct from patch and internal field + enthalpySorptionFvPatchScalarField + ( + const fvPatch&, + const DimensionedField& + ); + + //- Construct from patch, internal field and dictionary + enthalpySorptionFvPatchScalarField + ( + const fvPatch&, + const DimensionedField&, + const dictionary& + ); + + //- Construct by mapping given + //- enthalpySorptionFvPatchScalarField onto a new patch + enthalpySorptionFvPatchScalarField + ( + const enthalpySorptionFvPatchScalarField&, + const fvPatch&, + const DimensionedField&, + const fvPatchFieldMapper& + ); + + //- Construct as copy + enthalpySorptionFvPatchScalarField + ( + const enthalpySorptionFvPatchScalarField& + ); + + //- Construct and return a clone + virtual tmp clone() const + { + return tmp + ( + new enthalpySorptionFvPatchScalarField(*this) + ); + } + + //- Construct as copy setting internal field reference + enthalpySorptionFvPatchScalarField + ( + const enthalpySorptionFvPatchScalarField&, + const DimensionedField& + ); + + //- Construct and return a clone setting internal field reference + virtual tmp clone + ( + const DimensionedField& iF + ) const + { + return tmp + ( + new enthalpySorptionFvPatchScalarField(*this, iF) + ); + } + + + // Member Functions + + // Mapping + + //- Map (and resize as needed) from self given a mapping object + virtual void autoMap + ( + const fvPatchFieldMapper& + ); + + //- Reverse map the given fvPatchField onto this fvPatchField + virtual void rmap + ( + const fvPatchScalarField&, + const labelList& + ); + + + // Evaluation + + //- Source of cells next to the patch + virtual tmp patchSource() const; + + //- Update the coefficients associated with the patch field + virtual void updateCoeffs(); + + + // I-O + + //- Write + virtual void write(Ostream&) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* //