COxidationHurtMitchell.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2012-2016 OpenFOAM Foundation
9 Copyright (C) 2019 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27\*---------------------------------------------------------------------------*/
28
31
32// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
33
34template<class CloudType>
36(
37 const dictionary& dict,
38 CloudType& owner
39)
40:
41 SurfaceReactionModel<CloudType>(dict, owner, typeName),
42 Sb_(this->coeffDict().getScalar("Sb")),
43 CsLocalId_(-1),
44 ashLocalId_(-1),
45 O2GlobalId_(owner.composition().carrierId("O2")),
46 CO2GlobalId_(owner.composition().carrierId("CO2")),
47 WC_(0.0),
48 WO2_(0.0),
49 HcCO2_(0.0),
50 heatOfReaction_(-1.0)
51{
52 // Determine Cs and ash ids
53 label idSolid = owner.composition().idSolid();
54 CsLocalId_ = owner.composition().localId(idSolid, "C");
55 ashLocalId_ = owner.composition().localId(idSolid, "ash", true);
56
57 // Set local copies of thermo properties
58 WO2_ = owner.thermo().carrier().W(O2GlobalId_);
59 const scalar WCO2 = owner.thermo().carrier().W(CO2GlobalId_);
60 WC_ = WCO2 - WO2_;
61
62 HcCO2_ = owner.thermo().carrier().Hc(CO2GlobalId_);
63
64 const scalar YCloc = owner.composition().Y0(idSolid)[CsLocalId_];
65 const scalar YSolidTot = owner.composition().YMixture0()[idSolid];
66 Info<< " C(s): particle mass fraction = " << YCloc*YSolidTot << endl;
67
68 if (this->coeffDict().readIfPresent("heatOfReaction", heatOfReaction_))
69 {
70 Info<< " Using user specified heat of reaction: "
71 << heatOfReaction_ << " [J/kg]" << endl;
72 }
73}
74
75
76template<class CloudType>
78(
80)
81:
83 Sb_(srm.Sb_),
84 CsLocalId_(srm.CsLocalId_),
85 ashLocalId_(srm.ashLocalId_),
86 O2GlobalId_(srm.O2GlobalId_),
87 CO2GlobalId_(srm.CO2GlobalId_),
88 WC_(srm.WC_),
89 WO2_(srm.WO2_),
90 HcCO2_(srm.HcCO2_),
91 heatOfReaction_(srm.heatOfReaction_)
92{}
93
94
95// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
96
97template<class CloudType>
99(
100 const scalar dt,
101 const scalar Re,
102 const scalar nu,
103 const label celli,
104 const scalar d,
105 const scalar T,
106 const scalar Tc,
107 const scalar pc,
108 const scalar rhoc,
109 const scalar mass,
110 const scalarField& YGas,
111 const scalarField& YLiquid,
112 const scalarField& YSolid,
113 const scalarField& YMixture,
114 const scalar N,
115 scalarField& dMassGas,
116 scalarField& dMassLiquid,
117 scalarField& dMassSolid,
118 scalarField& dMassSRCarrier
119) const
120{
121 const label idGas = CloudType::parcelType::GAS;
122 const label idSolid = CloudType::parcelType::SLD;
123 const scalar Ychar = YMixture[idSolid]*YSolid[CsLocalId_];
124
125 // Surface combustion until combustible fraction is consumed
126 if (Ychar < SMALL)
127 {
128 return 0.0;
129 }
130
131 const SLGThermo& thermo = this->owner().thermo();
132
133 // Local mass fraction of O2 in the carrier phase
134 const scalar YO2 = thermo.carrier().Y(O2GlobalId_)[celli];
135
136 // No combustion if no oxygen present
137 if (YO2 < SMALL)
138 {
139 return 0.0;
140 }
141
142 // Conversion from [g/cm^2) to [kg/m^2]
143 const scalar convSI = 1000.0/10000.0;
144
145 // Universal gas constant in [kcal/mol/K]
146 const scalar RRcal = 1985.877534;
147
148 // Dry mass fraction
149 scalar Ydaf = YMixture[idGas] + YMixture[idSolid];
150 if (ashLocalId_ != -1)
151 {
152 Ydaf -= YMixture[idSolid]*YSolid[ashLocalId_];
153 }
154
155 // Char percentage
156 const scalar charPrc = max(0, min(Ychar/(Ydaf + ROOTVSMALL)*100.0, 100));
157
158 // Particle surface area
159 const scalar Ap = constant::mathematical::pi*sqr(d);
160
161 // Far field partial pressure O2 [Pa]
162 // Note: Should really use the surface partial pressure
163 const scalar ppO2 = max(0.0, rhoc*YO2/WO2_*RR*Tc);
164
165 // Activation energy [kcal/mol]
166 const scalar E = -5.94 + 0.355*charPrc;
167
168 // Pre-exponential factor [g/(cm^2.s.atm^0.5)]
169 const scalar lnK1750 = 2.8 - 0.0758*charPrc;
170 const scalar A = exp(lnK1750 + E/RRcal/1750.0);
171
172 // Kinetic rate of char oxidation [g/(cm^2.s.atm^0.5)]
173 const scalar Rk = A*exp(-E/(RRcal*T));
174
175 // Molar reaction rate per unit surface area [kmol/(m^2.s)]
176 const scalar qCsLim = mass*Ychar/(WC_*Ap*dt);
177 const scalar qCs = min(convSI*Rk*Foam::sqrt(ppO2/101325.0), qCsLim);
178
179 // Calculate the number of molar units reacted [kmol]
180 const scalar dOmega = qCs*Ap*dt;
181
182 // Add to carrier phase mass transfer
183 dMassSRCarrier[O2GlobalId_] += -dOmega*Sb_*WO2_;
184 dMassSRCarrier[CO2GlobalId_] += dOmega*(WC_ + Sb_*WO2_);
185
186 // Add to particle mass transfer
187 dMassSolid[CsLocalId_] += dOmega*WC_;
188
189
190 // Return the heat of reaction [J]
191 // note: carrier sensible enthalpy exchange handled via change in mass
192 if (heatOfReaction_ < 0)
193 {
194 const scalar HsC = thermo.solids().properties()[CsLocalId_].Hs(T);
195 return dOmega*(WC_*HsC - (WC_ + Sb_*WO2_)*HcCO2_);
196 }
197 else
198 {
199 return dOmega*WC_*heatOfReaction_;
200 }
201}
202
203
204// ************************************************************************* //
static const Foam::dimensionedScalar A("", Foam::dimPressure, 611.21)
Char oxidation model given by Hurt and Mitchell:
const CloudType & owner() const
Return const access to the owner cloud.
Templated base class for dsmc cloud.
Definition: DSMCCloud.H:75
Thermo package for (S)olids (L)iquids and (G)ases Takes reference to thermo package,...
Definition: SLGThermo.H:67
Templated surface reaction model class.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
const dictionary & coeffDict() const
Return const access to the coefficients dictionary.
Definition: subModelBase.C:131
Basic thermodynamics type based on the use of fitting functions for cp, h, s obtained from the templa...
basicSpecieMixture & composition
const volScalarField & T
constexpr scalar pi(M_PI)
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
dimensionedScalar exp(const dimensionedScalar &ds)
scalarField Re(const UList< complex > &cf)
Extract real component.
Definition: complexField.C:159
dimensionedSymmTensor sqr(const dimensionedVector &dv)
messageStream Info
Information stream (stdout output on master, null elsewhere)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
dimensionedScalar sqrt(const dimensionedScalar &ds)
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
volScalarField & nu
dictionary dict
propsDict readIfPresent("fields", acceptFields)
const Vector< label > N(dict.get< Vector< label > >("N"))