Cantera  3.1.0a4
Loading...
Searching...
No Matches
StFlow.cpp
Go to the documentation of this file.
1//! @file StFlow.cpp
2
3// This file is part of Cantera. See License.txt in the top-level directory or
4// at https://cantera.org/license.txt for license and copyright information.
5
8
9using namespace std;
10
11namespace Cantera
12{
13
14StFlow::StFlow(ThermoPhase* ph, size_t nsp, size_t points) :
15 Flow1D(ph, nsp, points)
16{
17 warn_deprecated("StFlow::StFlow",
18 "To be removed after Cantera 3.1. Class replaced by Flow1D.");
19}
20
21StFlow::StFlow(shared_ptr<ThermoPhase> th, size_t nsp, size_t points)
22 : Flow1D(th, nsp, points)
23{
24 warn_deprecated("StFlow::StFlow",
25 "To be removed after Cantera 3.1. Class replaced by Flow1D.");
26}
27
28StFlow::StFlow(shared_ptr<Solution> sol, const string& id, size_t points)
29 : Flow1D(sol, id, points)
30{
31 warn_deprecated("StFlow::StFlow",
32 "To be removed after Cantera 3.1. Class replaced by Flow1D.");
33}
34
35void StFlow::eval(size_t jg, double* xg, double* rg, integer* diagg, double rdt)
36{
37 // if evaluating a Jacobian, and the global point is outside the domain of
38 // influence for this domain, then skip evaluating the residual
39 if (jg != npos && (jg + 1 < firstPoint() || jg > lastPoint() + 1)) {
40 return;
41 }
42
43 // start of local part of global arrays
44 double* x = xg + loc();
45 double* rsd = rg + loc();
46 integer* diag = diagg + loc();
47
48 size_t jmin, jmax;
49 if (jg == npos) { // evaluate all points
50 jmin = 0;
51 jmax = m_points - 1;
52 } else { // evaluate points for Jacobian
53 size_t jpt = (jg == 0) ? 0 : jg - firstPoint();
54 jmin = std::max<size_t>(jpt, 1) - 1;
55 jmax = std::min(jpt+1,m_points-1);
56 }
57
58 updateProperties(jg, x, jmin, jmax);
59 evalResidual(x, rsd, diag, rdt, jmin, jmax);
60 evalUo(x, rsd, diag, rdt, jmin, jmax);
61}
62
63void StFlow::evalResidual(double* x, double* rsd, int* diag,
64 double rdt, size_t jmin, size_t jmax)
65{
66 //----------------------------------------------------
67 // evaluate the residual equations at all required
68 // grid points
69 //----------------------------------------------------
70
71 // calculation of qdotRadiation (see docstring of enableRadiation)
72 if (m_do_radiation) {
73 // variable definitions for the Planck absorption coefficient and the
74 // radiation calculation:
75 double k_P_ref = 1.0*OneAtm;
76
77 // polynomial coefficients:
78 const double c_H2O[6] = {-0.23093, -1.12390, 9.41530, -2.99880,
79 0.51382, -1.86840e-5};
80 const double c_CO2[6] = {18.741, -121.310, 273.500, -194.050,
81 56.310, -5.8169};
82
83 // calculation of the two boundary values
84 double boundary_Rad_left = m_epsilon_left * StefanBoltz * pow(T(x, 0), 4);
85 double boundary_Rad_right = m_epsilon_right * StefanBoltz * pow(T(x, m_points - 1), 4);
86
87 // loop over all grid points
88 for (size_t j = jmin; j < jmax; j++) {
89 // helping variable for the calculation
90 double radiative_heat_loss = 0;
91
92 // calculation of the mean Planck absorption coefficient
93 double k_P = 0;
94 // absorption coefficient for H2O
95 if (m_kRadiating[1] != npos) {
96 double k_P_H2O = 0;
97 for (size_t n = 0; n <= 5; n++) {
98 k_P_H2O += c_H2O[n] * pow(1000 / T(x, j), (double) n);
99 }
100 k_P_H2O /= k_P_ref;
101 k_P += m_press * X(x, m_kRadiating[1], j) * k_P_H2O;
102 }
103 // absorption coefficient for CO2
104 if (m_kRadiating[0] != npos) {
105 double k_P_CO2 = 0;
106 for (size_t n = 0; n <= 5; n++) {
107 k_P_CO2 += c_CO2[n] * pow(1000 / T(x, j), (double) n);
108 }
109 k_P_CO2 /= k_P_ref;
110 k_P += m_press * X(x, m_kRadiating[0], j) * k_P_CO2;
111 }
112
113 // calculation of the radiative heat loss term
114 radiative_heat_loss = 2 * k_P *(2 * StefanBoltz * pow(T(x, j), 4)
115 - boundary_Rad_left - boundary_Rad_right);
116
117 // set the radiative heat loss vector
118 m_qdotRadiation[j] = radiative_heat_loss;
119 }
120 }
121
122 for (size_t j = jmin; j <= jmax; j++) {
123 //----------------------------------------------
124 // left boundary
125 //----------------------------------------------
126
127 if (j == 0) {
128 // these may be modified by a boundary object
129
130 // Continuity. This propagates information right-to-left, since
131 // rho_u at point 0 is dependent on rho_u at point 1, but not on
132 // mdot from the inlet.
133 rsd[index(c_offset_U,0)] =
134 -(rho_u(x,1) - rho_u(x,0))/m_dz[0]
135 -(density(1)*V(x,1) + density(0)*V(x,0));
136
137 // the inlet (or other) object connected to this one will modify
138 // these equations by subtracting its values for V, T, and mdot. As
139 // a result, these residual equations will force the solution
140 // variables to the values for the boundary object
141 rsd[index(c_offset_V,0)] = V(x,0);
142 rsd[index(c_offset_T,0)] = T(x,0);
143 if (m_usesLambda) {
144 rsd[index(c_offset_L, 0)] = -rho_u(x, 0);
145 } else {
146 rsd[index(c_offset_L, 0)] = lambda(x, 0);
147 diag[index(c_offset_L, 0)] = 0;
148 }
149
150 // The default boundary condition for species is zero flux. However,
151 // the boundary object may modify this.
152 double sum = 0.0;
153 for (size_t k = 0; k < m_nsp; k++) {
154 sum += Y(x,k,0);
155 rsd[index(c_offset_Y + k, 0)] =
156 -(m_flux(k,0) + rho_u(x,0)* Y(x,k,0));
157 }
158 rsd[index(c_offset_Y + leftExcessSpecies(), 0)] = 1.0 - sum;
159
160 // set residual of poisson's equ to zero
161 rsd[index(c_offset_E, 0)] = x[index(c_offset_E, j)];
162 } else if (j == m_points - 1) {
163 evalRightBoundary(x, rsd, diag, rdt);
164 } else { // interior points
165 evalContinuity(j, x, rsd, diag, rdt);
166 // set residual of poisson's equ to zero
167 rsd[index(c_offset_E, j)] = x[index(c_offset_E, j)];
168
169 //------------------------------------------------
170 // Radial momentum equation
171 //
172 // \rho dV/dt + \rho u dV/dz + \rho V^2
173 // = d(\mu dV/dz)/dz - lambda
174 //-------------------------------------------------
175 if (m_usesLambda) {
176 rsd[index(c_offset_V,j)] =
177 (shear(x, j) - lambda(x, j) - rho_u(x, j) * dVdz(x, j)
178 - m_rho[j] * V(x, j) * V(x, j)) / m_rho[j]
179 - rdt * (V(x, j) - V_prev(j));
180 diag[index(c_offset_V, j)] = 1;
181 } else {
182 rsd[index(c_offset_V, j)] = V(x, j);
183 diag[index(c_offset_V, j)] = 0;
184 }
185
186 //-------------------------------------------------
187 // Species equations
188 //
189 // \rho dY_k/dt + \rho u dY_k/dz + dJ_k/dz
190 // = M_k\omega_k
191 //-------------------------------------------------
192 getWdot(x,j);
193 for (size_t k = 0; k < m_nsp; k++) {
194 double convec = rho_u(x,j)*dYdz(x,k,j);
195 double diffus = 2.0*(m_flux(k,j) - m_flux(k,j-1))
196 / (z(j+1) - z(j-1));
197 rsd[index(c_offset_Y + k, j)]
198 = (m_wt[k]*(wdot(k,j))
199 - convec - diffus)/m_rho[j]
200 - rdt*(Y(x,k,j) - Y_prev(k,j));
201 diag[index(c_offset_Y + k, j)] = 1;
202 }
203
204 //-----------------------------------------------
205 // energy equation
206 //
207 // \rho c_p dT/dt + \rho c_p u dT/dz
208 // = d(k dT/dz)/dz
209 // - sum_k(\omega_k h_k_ref)
210 // - sum_k(J_k c_p_k / M_k) dT/dz
211 //-----------------------------------------------
212 if (m_do_energy[j]) {
213
214 setGas(x,j);
215 double dtdzj = dTdz(x,j);
216 double sum = 0.0;
217
218 grad_hk(x, j);
219 for (size_t k = 0; k < m_nsp; k++) {
220 double flxk = 0.5*(m_flux(k,j-1) + m_flux(k,j));
221 sum += wdot(k,j)*m_hk(k,j);
222 sum += flxk * m_dhk_dz(k,j) / m_wt[k];
223 }
224
225 rsd[index(c_offset_T, j)] = - m_cp[j]*rho_u(x,j)*dtdzj
226 - conduction(x,j) - sum;
227 rsd[index(c_offset_T, j)] /= (m_rho[j]*m_cp[j]);
228 rsd[index(c_offset_T, j)] -= rdt*(T(x,j) - T_prev(j));
229 rsd[index(c_offset_T, j)] -= (m_qdotRadiation[j] / (m_rho[j] * m_cp[j]));
230 diag[index(c_offset_T, j)] = 1;
231 } else {
232 // residual equations if the energy equation is disabled
233 rsd[index(c_offset_T, j)] = T(x,j) - T_fixed(j);
234 diag[index(c_offset_T, j)] = 0;
235 }
236
237 if (m_usesLambda) {
238 rsd[index(c_offset_L, j)] = lambda(x, j) - lambda(x, j - 1);
239 } else {
240 rsd[index(c_offset_L, j)] = lambda(x, j);
241 }
242 diag[index(c_offset_L, j)] = 0;
243 }
244 }
245}
246
247void StFlow::evalRightBoundary(double* x, double* rsd, int* diag, double rdt)
248{
249 size_t j = m_points - 1;
250
251 // the boundary object connected to the right of this one may modify or
252 // replace these equations. The default boundary conditions are zero u, V,
253 // and T, and zero diffusive flux for all species.
254
255 rsd[index(c_offset_V,j)] = V(x,j);
256 diag[index(c_offset_V,j)] = 0;
257 double sum = 0.0;
258 // set residual of poisson's equ to zero
259 rsd[index(c_offset_E, j)] = x[index(c_offset_E, j)];
260 for (size_t k = 0; k < m_nsp; k++) {
261 sum += Y(x,k,j);
262 rsd[index(k+c_offset_Y,j)] = m_flux(k,j-1) + rho_u(x,j)*Y(x,k,j);
263 }
264 rsd[index(c_offset_Y + rightExcessSpecies(), j)] = 1.0 - sum;
265 diag[index(c_offset_Y + rightExcessSpecies(), j)] = 0;
266 if (m_usesLambda) {
267 rsd[index(c_offset_U, j)] = rho_u(x, j);
268 } else {
269 rsd[index(c_offset_U, j)] = rho_u(x, j) - rho_u(x, j-1);
270 }
271
272 rsd[index(c_offset_L, j)] = lambda(x, j) - lambda(x, j-1);
273 diag[index(c_offset_L, j)] = 0;
274 rsd[index(c_offset_T, j)] = T(x, j);
275}
276
277void StFlow::evalContinuity(size_t j, double* x, double* rsd, int* diag, double rdt)
278{
279 //algebraic constraint
280 diag[index(c_offset_U, j)] = 0;
281 //----------------------------------------------
282 // Continuity equation
283 //
284 // d(\rho u)/dz + 2\rho V = 0
285 //----------------------------------------------
286 if (m_usesLambda) {
287 // Note that this propagates the mass flow rate information to the left
288 // (j+1 -> j) from the value specified at the right boundary. The
289 // lambda information propagates in the opposite direction.
290 rsd[index(c_offset_U,j)] =
291 -(rho_u(x,j+1) - rho_u(x,j))/m_dz[j]
292 -(density(j+1)*V(x,j+1) + density(j)*V(x,j));
293 } else if (m_isFree) {
294 // terms involving V are zero as V=0 by definition
295 if (grid(j) > m_zfixed) {
296 rsd[index(c_offset_U,j)] =
297 - (rho_u(x,j) - rho_u(x,j-1))/m_dz[j-1];
298 } else if (grid(j) == m_zfixed) {
299 if (m_do_energy[j]) {
300 rsd[index(c_offset_U,j)] = (T(x,j) - m_tfixed);
301 } else {
302 rsd[index(c_offset_U,j)] = (rho_u(x,j)
303 - m_rho[0]*0.3); // why 0.3?
304 }
305 } else if (grid(j) < m_zfixed) {
306 rsd[index(c_offset_U,j)] =
307 - (rho_u(x,j+1) - rho_u(x,j))/m_dz[j];
308 }
309 } else {
310 // unstrained with fixed mass flow rate
311 rsd[index(c_offset_U, j)] = rho_u(x, j) - rho_u(x, j - 1);
312 }
313}
314
315} // namespace
size_t lastPoint() const
The index of the last (that is, right-most) grid point belonging to this domain.
Definition Domain1D.h:428
size_t m_points
Number of grid points.
Definition Domain1D.h:566
size_t firstPoint() const
The index of the first (that is, left-most) grid point belonging to this domain.
Definition Domain1D.h:420
size_t index(size_t n, size_t j) const
Returns the index of the solution vector, which corresponds to component n at grid point j.
Definition Domain1D.h:330
virtual size_t loc(size_t j=0) const
Location of the start of the local solution vector in the global solution vector,.
Definition Domain1D.h:412
This class represents 1D flow domains that satisfy the one-dimensional similarity solution for chemic...
Definition Flow1D.h:46
double dYdz(const double *x, size_t k, size_t j) const
Calculates the spatial derivative of the species mass fraction with respect to z for species k at po...
Definition Flow1D.h:719
double dTdz(const double *x, size_t j) const
Calculates the spatial derivative of temperature T with respect to z at point j using upwind differen...
Definition Flow1D.h:733
size_t rightExcessSpecies() const
Index of the species on the right boundary with the largest mass fraction.
Definition Flow1D.h:390
vector< double > m_qdotRadiation
radiative heat loss vector
Definition Flow1D.h:875
double dVdz(const double *x, size_t j) const
Calculates the spatial derivative of velocity V with respect to z at point j using upwind differencin...
Definition Flow1D.h:704
vector< double > m_cp
Vector of size m_nsp to cache specific heat capacities.
Definition Flow1D.h:821
double shear(const double *x, size_t j) const
Compute the shear term from the momentum equation using a central three-point differencing scheme.
Definition Flow1D.h:761
vector< double > m_rho
Vector of size m_nsp to cache densities.
Definition Flow1D.h:816
Array2D m_flux
Array of size m_nsp by m_points for saving diffusive mass fluxes.
Definition Flow1D.h:839
void setGas(const double *x, size_t j)
Set the gas object state to be consistent with the solution at point j.
Definition Flow1D.cpp:241
double m_tfixed
Temperature at the point used to fix the flame location.
Definition Flow1D.h:912
Array2D m_hk
Array of size m_nsp by m_points for saving molar enthalpies.
Definition Flow1D.h:842
double conduction(const double *x, size_t j) const
Compute the conduction term from the energy equation using a central three-point differencing scheme.
Definition Flow1D.h:776
size_t leftExcessSpecies() const
Index of the species on the left boundary with the largest mass fraction.
Definition Flow1D.h:385
Array2D m_dhk_dz
Array of size m_nsp by m_points-1 for saving enthalpy fluxes.
Definition Flow1D.h:845
double m_zfixed
Location of the point where temperature is fixed.
Definition Flow1D.h:909
size_t m_nsp
Number of species in the mechanism.
Definition Flow1D.h:850
virtual void grad_hk(const double *x, size_t j)
Compute the spatial derivative of species specific molar enthalpies using upwind differencing.
Definition Flow1D.cpp:1159
virtual void updateProperties(size_t jg, double *x, size_t jmin, size_t jmax)
Update the properties (thermo, transport, and diffusion flux).
Definition Flow1D.cpp:347
virtual void evalUo(double *x, double *rsd, int *diag, double rdt, size_t jmin, size_t jmax)
Evaluate the oxidizer axial velocity equation residual.
Definition Flow1D.cpp:690
vector< size_t > m_kRadiating
Indices within the ThermoPhase of the radiating species.
Definition Flow1D.h:862
double T_fixed(size_t j) const
The fixed temperature value at point j.
Definition Flow1D.h:162
bool m_do_radiation
flag for the radiative heat loss
Definition Flow1D.h:872
virtual void evalResidual(double *x, double *rsd, int *diag, double rdt, size_t jmin, size_t jmax)
Evaluate the residual function.
Definition StFlow.cpp:63
virtual void evalRightBoundary(double *x, double *res, int *diag, double rdt)
Evaluate all residual components at the right boundary.
Definition StFlow.cpp:247
StFlow(ThermoPhase *ph=0, size_t nsp=1, size_t points=1)
Create a new flow domain.
Definition StFlow.cpp:14
void evalContinuity(size_t j, double *x, double *r, int *diag, double rdt) override
Alternate version of evalContinuity with legacy signature.
Definition StFlow.cpp:277
void eval(size_t j, double *x, double *r, integer *mask, double rdt) override
Evaluate the residual functions for axisymmetric stagnation flow.
Definition StFlow.cpp:35
void getWdot(double *x, size_t j)
Write the net production rates at point j into array m_wdot
Definition StFlow.h:54
Base class for a phase with thermodynamic properties.
This file contains definitions for utility functions and text for modules, inputfiles and logging,...
const double OneAtm
One atmosphere [Pa].
Definition ct_defs.h:96
const double StefanBoltz
Stefan-Boltzmann constant [W/m2/K4].
Definition ct_defs.h:128
Namespace for the Cantera kernel.
Definition AnyMap.cpp:595
const size_t npos
index returned by functions to indicate "no position"
Definition ct_defs.h:180
@ c_offset_U
axial velocity [m/s]
Definition Flow1D.h:25
@ c_offset_L
(1/r)dP/dr
Definition Flow1D.h:28
@ c_offset_V
strain rate
Definition Flow1D.h:26
@ c_offset_E
electric field
Definition Flow1D.h:29
@ c_offset_Y
mass fractions
Definition Flow1D.h:31
@ c_offset_T
temperature [kelvin]
Definition Flow1D.h:27
void warn_deprecated(const string &source, const AnyBase &node, const string &message)
A deprecation warning for syntax in an input file.
Definition AnyMap.cpp:1997