Cantera  3.0.0
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#include "cantera/oneD/refine.h"
12#include "cantera/base/global.h"
13
14using namespace std;
15
16namespace Cantera
17{
18
19StFlow::StFlow(ThermoPhase* ph, size_t nsp, size_t points) :
20 Domain1D(nsp+c_offset_Y, points),
21 m_nsp(nsp)
22{
23 m_type = cFlowType;
24 m_points = points;
25
26 if (ph == 0) {
27 return; // used to create a dummy object
28 }
29 m_thermo = ph;
30
31 size_t nsp2 = m_thermo->nSpecies();
32 if (nsp2 != m_nsp) {
33 m_nsp = nsp2;
35 }
36
37 // make a local copy of the species molecular weight vector
38 m_wt = m_thermo->molecularWeights();
39
40 // set pressure based on associated thermo object
41 setPressure(m_thermo->pressure());
42
43 // the species mass fractions are the last components in the solution
44 // vector, so the total number of components is the number of species
45 // plus the offset of the first mass fraction.
46 m_nv = c_offset_Y + m_nsp;
47
48 // enable all species equations by default
49 m_do_species.resize(m_nsp, true);
50
51 // but turn off the energy equation at all points
52 m_do_energy.resize(m_points,false);
53
54 m_diff.resize(m_nsp*m_points);
55 m_multidiff.resize(m_nsp*m_nsp*m_points);
56 m_flux.resize(m_nsp,m_points);
57 m_wdot.resize(m_nsp,m_points, 0.0);
59 m_dhk_dz.resize(m_nsp, m_points - 1, 0.0);
60 m_ybar.resize(m_nsp);
61 m_qdotRadiation.resize(m_points, 0.0);
62
63 //-------------- default solution bounds --------------------
64 setBounds(c_offset_U, -1e20, 1e20); // no bounds on u
65 setBounds(c_offset_V, -1e20, 1e20); // V
66 setBounds(c_offset_T, 200.0, 2*m_thermo->maxTemp()); // temperature bounds
67 setBounds(c_offset_L, -1e20, 1e20); // lambda should be negative
68 setBounds(c_offset_E, -1e20, 1e20); // no bounds for inactive component
69
70 // mass fraction bounds
71 for (size_t k = 0; k < m_nsp; k++) {
72 setBounds(c_offset_Y+k, -1.0e-7, 1.0e5);
73 }
74
75 //-------------------- grid refinement -------------------------
76 m_refiner->setActive(c_offset_U, false);
77 m_refiner->setActive(c_offset_V, false);
78 m_refiner->setActive(c_offset_T, false);
79 m_refiner->setActive(c_offset_L, false);
80
81 vector<double> gr;
82 for (size_t ng = 0; ng < m_points; ng++) {
83 gr.push_back(1.0*ng/m_points);
84 }
85 setupGrid(m_points, gr.data());
86
87 // Find indices for radiating species
88 m_kRadiating.resize(2, npos);
89 m_kRadiating[0] = m_thermo->speciesIndex("CO2");
90 m_kRadiating[1] = m_thermo->speciesIndex("H2O");
91}
92
93StFlow::StFlow(shared_ptr<ThermoPhase> th, size_t nsp, size_t points)
94 : StFlow(th.get(), nsp, points)
95{
97 m_solution->setThermo(th);
98}
99
100StFlow::StFlow(shared_ptr<Solution> sol, const string& id, size_t points)
101 : StFlow(sol->thermo().get(), sol->thermo()->nSpecies(), points)
102{
103 m_solution = sol;
104 m_id = id;
105 m_kin = m_solution->kinetics().get();
106 m_trans = m_solution->transport().get();
107 if (m_trans->transportModel() == "none") {
108 // @deprecated
109 warn_deprecated("StFlow",
110 "An appropriate transport model\nshould be set when instantiating the "
111 "Solution ('gas') object.\nImplicit setting of the transport model "
112 "is deprecated and\nwill be removed after Cantera 3.0.");
113 setTransportModel("mixture-averaged");
114 }
115 m_solution->registerChangedCallback(this, [this]() {
116 setKinetics(m_solution->kinetics());
117 setTransport(m_solution->transport());
118 });
119}
120
121StFlow::~StFlow()
122{
123 if (m_solution) {
124 m_solution->removeChangedCallback(this);
125 }
126}
127
128string StFlow::type() const {
129 if (m_isFree) {
130 return "free-flow";
131 }
132 if (m_usesLambda) {
133 return "axisymmetric-flow";
134 }
135 return "unstrained-flow";
136}
137
139 warn_deprecated("StFlow::setThermo", "To be removed after Cantera 3.0.");
140 m_thermo = &th;
141}
142
143void StFlow::setKinetics(shared_ptr<Kinetics> kin)
144{
145 if (!m_solution) {
146 // @todo remove after Cantera 3.0
147 throw CanteraError("StFlow::setKinetics",
148 "Unable to update object that was not constructed from smart pointers.");
149 }
150 m_kin = kin.get();
151 m_solution->setKinetics(kin);
152}
153
155{
156 warn_deprecated("StFlow::setKinetics(Kinetics&)", "To be removed after Cantera 3.0."
157 " Replaced by setKinetics(shared_ptr<Kinetics>).");
158 m_kin = &kin;
159}
160
161void StFlow::setTransport(shared_ptr<Transport> trans)
162{
163 if (!m_solution) {
164 // @todo remove after Cantera 3.0
165 throw CanteraError("StFlow::setTransport",
166 "Unable to update object that was not constructed from smart pointers.");
167 }
168 if (!trans) {
169 throw CanteraError("StFlow::setTransport", "Unable to set empty transport.");
170 }
171 m_trans = trans.get();
172 if (m_trans->transportModel() == "none") {
173 throw CanteraError("StFlow::setTransport", "Invalid Transport model 'none'.");
174 }
175 m_do_multicomponent = (m_trans->transportModel() == "multicomponent" ||
176 m_trans->transportModel() == "multicomponent-CK");
177
178 m_diff.resize(m_nsp * m_points);
179 if (m_do_multicomponent) {
180 m_multidiff.resize(m_nsp * m_nsp*m_points);
181 m_dthermal.resize(m_nsp, m_points, 0.0);
182 }
183 m_solution->setTransport(trans);
184}
185
186void StFlow::resize(size_t ncomponents, size_t points)
187{
188 Domain1D::resize(ncomponents, points);
189 m_rho.resize(m_points, 0.0);
190 m_wtm.resize(m_points, 0.0);
191 m_cp.resize(m_points, 0.0);
192 m_visc.resize(m_points, 0.0);
193 m_tcon.resize(m_points, 0.0);
194
195 m_diff.resize(m_nsp*m_points);
196 if (m_do_multicomponent) {
197 m_multidiff.resize(m_nsp*m_nsp*m_points);
198 m_dthermal.resize(m_nsp, m_points, 0.0);
199 }
200 m_flux.resize(m_nsp,m_points);
201 m_wdot.resize(m_nsp,m_points, 0.0);
202 m_hk.resize(m_nsp, m_points, 0.0);
203 m_dhk_dz.resize(m_nsp, m_points - 1, 0.0);
204 m_do_energy.resize(m_points,false);
205 m_qdotRadiation.resize(m_points, 0.0);
206 m_fixedtemp.resize(m_points);
207
208 m_dz.resize(m_points-1);
209 m_z.resize(m_points);
210}
211
212void StFlow::setupGrid(size_t n, const double* z)
213{
214 resize(m_nv, n);
215
216 m_z[0] = z[0];
217 for (size_t j = 1; j < m_points; j++) {
218 if (z[j] <= z[j-1]) {
219 throw CanteraError("StFlow::setupGrid",
220 "grid points must be monotonically increasing");
221 }
222 m_z[j] = z[j];
223 m_dz[j-1] = m_z[j] - m_z[j-1];
224 }
225}
226
228{
229 double* x = xg + loc();
230 for (size_t j = 0; j < m_points; j++) {
231 double* Y = x + m_nv*j + c_offset_Y;
232 m_thermo->setMassFractions(Y);
233 m_thermo->getMassFractions(Y);
234 }
235}
236
237void StFlow::setTransportModel(const string& trans)
238{
239 if (!m_solution) {
240 // @todo remove after Cantera 3.0
241 throw CanteraError("StFlow::setTransportModel",
242 "Unable to set Transport manager by name as object was not initialized\n"
243 "from a Solution manager: set Transport object directly instead.");
244 }
245 m_solution->setTransportModel(trans);
246}
247
249 return m_trans->transportModel();
250}
251
253{
254 warn_deprecated("StFlow::setTransport(Transport&)", "To be removed after"
255 " Cantera 3.0. Replaced by setTransport(shared_ptr<Transport>).");
256 m_trans = &trans;
257 if (m_trans->transportModel() == "none") {
258 throw CanteraError("StFlow::setTransport",
259 "Invalid Transport model 'none'.");
260 }
261 m_do_multicomponent = (m_trans->transportModel() == "multicomponent" ||
262 m_trans->transportModel() == "multicomponent-CK");
263
264 m_diff.resize(m_nsp*m_points);
265 if (m_do_multicomponent) {
266 m_multidiff.resize(m_nsp*m_nsp*m_points);
267 m_dthermal.resize(m_nsp, m_points, 0.0);
268 }
269}
270
272{
273 for (size_t j = 0; j < m_points; j++) {
274 T(x,j) = m_thermo->temperature();
275 m_thermo->getMassFractions(&Y(x, 0, j));
276 m_rho[j] = m_thermo->density();
277 }
278}
279
280void StFlow::setGas(const double* x, size_t j)
281{
282 m_thermo->setTemperature(T(x,j));
283 const double* yy = x + m_nv*j + c_offset_Y;
284 m_thermo->setMassFractions_NoNorm(yy);
285 m_thermo->setPressure(m_press);
286}
287
288void StFlow::setGasAtMidpoint(const double* x, size_t j)
289{
290 m_thermo->setTemperature(0.5*(T(x,j)+T(x,j+1)));
291 const double* yyj = x + m_nv*j + c_offset_Y;
292 const double* yyjp = x + m_nv*(j+1) + c_offset_Y;
293 for (size_t k = 0; k < m_nsp; k++) {
294 m_ybar[k] = 0.5*(yyj[k] + yyjp[k]);
295 }
296 m_thermo->setMassFractions_NoNorm(m_ybar.data());
297 m_thermo->setPressure(m_press);
298}
299
301 warn_deprecated("StFlow::fixed_mdot", "To be removed after"
302 " Cantera 3.0. Replaced by isFree().");
303 return !m_isFree;
304}
305
306void StFlow::_finalize(const double* x)
307{
308 if (!m_do_multicomponent && m_do_soret) {
309 throw CanteraError("StFlow::_finalize",
310 "Thermal diffusion (the Soret effect) is enabled, and requires "
311 "using a multicomponent transport model.");
312 }
313
314 size_t nz = m_zfix.size();
315 bool e = m_do_energy[0];
316 for (size_t j = 0; j < m_points; j++) {
317 if (e || nz == 0) {
318 m_fixedtemp[j] = T(x, j);
319 } else {
320 double zz = (z(j) - z(0))/(z(m_points - 1) - z(0));
321 double tt = linearInterp(zz, m_zfix, m_tfix);
322 m_fixedtemp[j] = tt;
323 }
324 }
325 if (e) {
326 solveEnergyEqn();
327 }
328
329 if (m_isFree) {
330 // If the domain contains the temperature fixed point, make sure that it
331 // is correctly set. This may be necessary when the grid has been modified
332 // externally.
333 if (m_tfixed != Undef) {
334 for (size_t j = 0; j < m_points; j++) {
335 if (z(j) == m_zfixed) {
336 return; // fixed point is already set correctly
337 }
338 }
339
340 for (size_t j = 0; j < m_points - 1; j++) {
341 // Find where the temperature profile crosses the current
342 // fixed temperature.
343 if ((T(x, j) - m_tfixed) * (T(x, j+1) - m_tfixed) <= 0.0) {
344 m_tfixed = T(x, j+1);
345 m_zfixed = z(j+1);
346 return;
347 }
348 }
349 }
350 }
351}
352
353void StFlow::eval(size_t jg, double* xg, double* rg, integer* diagg, double rdt)
354{
355 // if evaluating a Jacobian, and the global point is outside the domain of
356 // influence for this domain, then skip evaluating the residual
357 if (jg != npos && (jg + 1 < firstPoint() || jg > lastPoint() + 1)) {
358 return;
359 }
360
361 // start of local part of global arrays
362 double* x = xg + loc();
363 double* rsd = rg + loc();
364 integer* diag = diagg + loc();
365
366 size_t jmin, jmax;
367 if (jg == npos) { // evaluate all points
368 jmin = 0;
369 jmax = m_points - 1;
370 } else { // evaluate points for Jacobian
371 size_t jpt = (jg == 0) ? 0 : jg - firstPoint();
372 jmin = std::max<size_t>(jpt, 1) - 1;
373 jmax = std::min(jpt+1,m_points-1);
374 }
375
376 updateProperties(jg, x, jmin, jmax);
377 evalResidual(x, rsd, diag, rdt, jmin, jmax);
378}
379
380void StFlow::updateProperties(size_t jg, double* x, size_t jmin, size_t jmax)
381{
382 // properties are computed for grid points from j0 to j1
383 size_t j0 = std::max<size_t>(jmin, 1) - 1;
384 size_t j1 = std::min(jmax+1,m_points-1);
385
386 updateThermo(x, j0, j1);
387 if (jg == npos || m_force_full_update) {
388 // update transport properties only if a Jacobian is not being
389 // evaluated, or if specifically requested
390 updateTransport(x, j0, j1);
391 }
392 if (jg == npos) {
393 double* Yleft = x + index(c_offset_Y, jmin);
394 m_kExcessLeft = distance(Yleft, max_element(Yleft, Yleft + m_nsp));
395 double* Yright = x + index(c_offset_Y, jmax);
396 m_kExcessRight = distance(Yright, max_element(Yright, Yright + m_nsp));
397 }
398
399 // update the species diffusive mass fluxes whether or not a
400 // Jacobian is being evaluated
401 updateDiffFluxes(x, j0, j1);
402}
403
404void StFlow::evalResidual(double* x, double* rsd, int* diag,
405 double rdt, size_t jmin, size_t jmax)
406{
407 //----------------------------------------------------
408 // evaluate the residual equations at all required
409 // grid points
410 //----------------------------------------------------
411
412 // calculation of qdotRadiation (see docstring of enableRadiation)
413 if (m_do_radiation) {
414 // variable definitions for the Planck absorption coefficient and the
415 // radiation calculation:
416 double k_P_ref = 1.0*OneAtm;
417
418 // polynomial coefficients:
419 const double c_H2O[6] = {-0.23093, -1.12390, 9.41530, -2.99880,
420 0.51382, -1.86840e-5};
421 const double c_CO2[6] = {18.741, -121.310, 273.500, -194.050,
422 56.310, -5.8169};
423
424 // calculation of the two boundary values
425 double boundary_Rad_left = m_epsilon_left * StefanBoltz * pow(T(x, 0), 4);
426 double boundary_Rad_right = m_epsilon_right * StefanBoltz * pow(T(x, m_points - 1), 4);
427
428 // loop over all grid points
429 for (size_t j = jmin; j < jmax; j++) {
430 // helping variable for the calculation
431 double radiative_heat_loss = 0;
432
433 // calculation of the mean Planck absorption coefficient
434 double k_P = 0;
435 // absorption coefficient for H2O
436 if (m_kRadiating[1] != npos) {
437 double k_P_H2O = 0;
438 for (size_t n = 0; n <= 5; n++) {
439 k_P_H2O += c_H2O[n] * pow(1000 / T(x, j), (double) n);
440 }
441 k_P_H2O /= k_P_ref;
442 k_P += m_press * X(x, m_kRadiating[1], j) * k_P_H2O;
443 }
444 // absorption coefficient for CO2
445 if (m_kRadiating[0] != npos) {
446 double k_P_CO2 = 0;
447 for (size_t n = 0; n <= 5; n++) {
448 k_P_CO2 += c_CO2[n] * pow(1000 / T(x, j), (double) n);
449 }
450 k_P_CO2 /= k_P_ref;
451 k_P += m_press * X(x, m_kRadiating[0], j) * k_P_CO2;
452 }
453
454 // calculation of the radiative heat loss term
455 radiative_heat_loss = 2 * k_P *(2 * StefanBoltz * pow(T(x, j), 4)
456 - boundary_Rad_left - boundary_Rad_right);
457
458 // set the radiative heat loss vector
459 m_qdotRadiation[j] = radiative_heat_loss;
460 }
461 }
462
463 for (size_t j = jmin; j <= jmax; j++) {
464 //----------------------------------------------
465 // left boundary
466 //----------------------------------------------
467
468 if (j == 0) {
469 // these may be modified by a boundary object
470
471 // Continuity. This propagates information right-to-left, since
472 // rho_u at point 0 is dependent on rho_u at point 1, but not on
473 // mdot from the inlet.
474 rsd[index(c_offset_U,0)] =
475 -(rho_u(x,1) - rho_u(x,0))/m_dz[0]
476 -(density(1)*V(x,1) + density(0)*V(x,0));
477
478 // the inlet (or other) object connected to this one will modify
479 // these equations by subtracting its values for V, T, and mdot. As
480 // a result, these residual equations will force the solution
481 // variables to the values for the boundary object
482 rsd[index(c_offset_V,0)] = V(x,0);
483 rsd[index(c_offset_T,0)] = T(x,0);
484 if (m_usesLambda) {
485 rsd[index(c_offset_L, 0)] = -rho_u(x, 0);
486 } else {
487 rsd[index(c_offset_L, 0)] = lambda(x, 0);
488 diag[index(c_offset_L, 0)] = 0;
489 }
490
491 // The default boundary condition for species is zero flux. However,
492 // the boundary object may modify this.
493 double sum = 0.0;
494 for (size_t k = 0; k < m_nsp; k++) {
495 sum += Y(x,k,0);
496 rsd[index(c_offset_Y + k, 0)] =
497 -(m_flux(k,0) + rho_u(x,0)* Y(x,k,0));
498 }
499 rsd[index(c_offset_Y + leftExcessSpecies(), 0)] = 1.0 - sum;
500
501 // set residual of poisson's equ to zero
502 rsd[index(c_offset_E, 0)] = x[index(c_offset_E, j)];
503 } else if (j == m_points - 1) {
504 evalRightBoundary(x, rsd, diag, rdt);
505 } else { // interior points
506 evalContinuity(j, x, rsd, diag, rdt);
507 // set residual of poisson's equ to zero
508 rsd[index(c_offset_E, j)] = x[index(c_offset_E, j)];
509
510 //------------------------------------------------
511 // Radial momentum equation
512 //
513 // \rho dV/dt + \rho u dV/dz + \rho V^2
514 // = d(\mu dV/dz)/dz - lambda
515 //-------------------------------------------------
516 if (m_usesLambda) {
517 rsd[index(c_offset_V,j)] =
518 (shear(x, j) - lambda(x, j) - rho_u(x, j) * dVdz(x, j)
519 - m_rho[j] * V(x, j) * V(x, j)) / m_rho[j]
520 - rdt * (V(x, j) - V_prev(j));
521 diag[index(c_offset_V, j)] = 1;
522 } else {
523 rsd[index(c_offset_V, j)] = V(x, j);
524 diag[index(c_offset_V, j)] = 0;
525 }
526
527 //-------------------------------------------------
528 // Species equations
529 //
530 // \rho dY_k/dt + \rho u dY_k/dz + dJ_k/dz
531 // = M_k\omega_k
532 //-------------------------------------------------
533 getWdot(x,j);
534 for (size_t k = 0; k < m_nsp; k++) {
535 double convec = rho_u(x,j)*dYdz(x,k,j);
536 double diffus = 2.0*(m_flux(k,j) - m_flux(k,j-1))
537 / (z(j+1) - z(j-1));
538 rsd[index(c_offset_Y + k, j)]
539 = (m_wt[k]*(wdot(k,j))
540 - convec - diffus)/m_rho[j]
541 - rdt*(Y(x,k,j) - Y_prev(k,j));
542 diag[index(c_offset_Y + k, j)] = 1;
543 }
544
545 //-----------------------------------------------
546 // energy equation
547 //
548 // \rho c_p dT/dt + \rho c_p u dT/dz
549 // = d(k dT/dz)/dz
550 // - sum_k(\omega_k h_k_ref)
551 // - sum_k(J_k c_p_k / M_k) dT/dz
552 //-----------------------------------------------
553 if (m_do_energy[j]) {
554
555 setGas(x,j);
556 double dtdzj = dTdz(x,j);
557 double sum = 0.0;
558
559 grad_hk(x, j);
560 for (size_t k = 0; k < m_nsp; k++) {
561 double flxk = 0.5*(m_flux(k,j-1) + m_flux(k,j));
562 sum += wdot(k,j)*m_hk(k,j);
563 sum += flxk * m_dhk_dz(k,j) / m_wt[k];
564 }
565
566 rsd[index(c_offset_T, j)] = - m_cp[j]*rho_u(x,j)*dtdzj
567 - divHeatFlux(x,j) - sum;
568 rsd[index(c_offset_T, j)] /= (m_rho[j]*m_cp[j]);
569 rsd[index(c_offset_T, j)] -= rdt*(T(x,j) - T_prev(j));
570 rsd[index(c_offset_T, j)] -= (m_qdotRadiation[j] / (m_rho[j] * m_cp[j]));
571 diag[index(c_offset_T, j)] = 1;
572 } else {
573 // residual equations if the energy equation is disabled
574 rsd[index(c_offset_T, j)] = T(x,j) - T_fixed(j);
575 diag[index(c_offset_T, j)] = 0;
576 }
577
578 if (m_usesLambda) {
579 rsd[index(c_offset_L, j)] = lambda(x, j) - lambda(x, j - 1);
580 } else {
581 rsd[index(c_offset_L, j)] = lambda(x, j);
582 }
583 diag[index(c_offset_L, j)] = 0;
584 }
585 }
586}
587
588void StFlow::updateTransport(double* x, size_t j0, size_t j1)
589{
590 if (m_do_multicomponent) {
591 for (size_t j = j0; j < j1; j++) {
592 setGasAtMidpoint(x,j);
593 double wtm = m_thermo->meanMolecularWeight();
594 double rho = m_thermo->density();
595 m_visc[j] = (m_dovisc ? m_trans->viscosity() : 0.0);
596 m_trans->getMultiDiffCoeffs(m_nsp, &m_multidiff[mindex(0,0,j)]);
597
598 // Use m_diff as storage for the factor outside the summation
599 for (size_t k = 0; k < m_nsp; k++) {
600 m_diff[k+j*m_nsp] = m_wt[k] * rho / (wtm*wtm);
601 }
602
603 m_tcon[j] = m_trans->thermalConductivity();
604 if (m_do_soret) {
605 m_trans->getThermalDiffCoeffs(m_dthermal.ptrColumn(0) + j*m_nsp);
606 }
607 }
608 } else { // mixture averaged transport
609 for (size_t j = j0; j < j1; j++) {
610 setGasAtMidpoint(x,j);
611 m_visc[j] = (m_dovisc ? m_trans->viscosity() : 0.0);
612 m_trans->getMixDiffCoeffs(&m_diff[j*m_nsp]);
613 m_tcon[j] = m_trans->thermalConductivity();
614 }
615 }
616}
617
618void StFlow::show(const double* x)
619{
620 writelog(" Pressure: {:10.4g} Pa\n", m_press);
621
623
624 if (m_do_radiation) {
625 writeline('-', 79, false, true);
626 writelog("\n z radiative heat loss");
627 writeline('-', 79, false, true);
628 for (size_t j = 0; j < m_points; j++) {
629 writelog("\n {:10.4g} {:10.4g}", m_z[j], m_qdotRadiation[j]);
630 }
631 writelog("\n");
632 }
633}
634
635void StFlow::updateDiffFluxes(const double* x, size_t j0, size_t j1)
636{
637 if (m_do_multicomponent) {
638 for (size_t j = j0; j < j1; j++) {
639 double dz = z(j+1) - z(j);
640 for (size_t k = 0; k < m_nsp; k++) {
641 double sum = 0.0;
642 for (size_t m = 0; m < m_nsp; m++) {
643 sum += m_wt[m] * m_multidiff[mindex(k,m,j)] * (X(x,m,j+1)-X(x,m,j));
644 }
645 m_flux(k,j) = sum * m_diff[k+j*m_nsp] / dz;
646 }
647 }
648 } else {
649 for (size_t j = j0; j < j1; j++) {
650 double sum = 0.0;
651 double wtm = m_wtm[j];
652 double rho = density(j);
653 double dz = z(j+1) - z(j);
654 for (size_t k = 0; k < m_nsp; k++) {
655 m_flux(k,j) = m_wt[k]*(rho*m_diff[k+m_nsp*j]/wtm);
656 m_flux(k,j) *= (X(x,k,j) - X(x,k,j+1))/dz;
657 sum -= m_flux(k,j);
658 }
659 // correction flux to insure that \sum_k Y_k V_k = 0.
660 for (size_t k = 0; k < m_nsp; k++) {
661 m_flux(k,j) += sum*Y(x,k,j);
662 }
663 }
664 }
665
666 if (m_do_soret) {
667 for (size_t m = j0; m < j1; m++) {
668 double gradlogT = 2.0 * (T(x,m+1) - T(x,m)) /
669 ((T(x,m+1) + T(x,m)) * (z(m+1) - z(m)));
670 for (size_t k = 0; k < m_nsp; k++) {
671 m_flux(k,m) -= m_dthermal(k,m)*gradlogT;
672 }
673 }
674 }
675}
676
677string StFlow::componentName(size_t n) const
678{
679 switch (n) {
680 case c_offset_U:
681 return "velocity";
682 case c_offset_V:
683 return "spread_rate";
684 case c_offset_T:
685 return "T";
686 case c_offset_L:
687 return "lambda";
688 case c_offset_E:
689 return "eField";
690 default:
691 if (n >= c_offset_Y && n < (c_offset_Y + m_nsp)) {
692 return m_thermo->speciesName(n - c_offset_Y);
693 } else {
694 return "<unknown>";
695 }
696 }
697}
698
699size_t StFlow::componentIndex(const string& name) const
700{
701 if (name=="velocity") {
702 return c_offset_U;
703 } else if (name=="spread_rate") {
704 return c_offset_V;
705 } else if (name=="T") {
706 return c_offset_T;
707 } else if (name=="lambda") {
708 return c_offset_L;
709 } else if (name == "eField") {
710 return c_offset_E;
711 } else {
712 for (size_t n=c_offset_Y; n<m_nsp+c_offset_Y; n++) {
713 if (componentName(n)==name) {
714 return n;
715 }
716 }
717 throw CanteraError("StFlow1D::componentIndex",
718 "no component named " + name);
719 }
720}
721
722bool StFlow::componentActive(size_t n) const
723{
724 switch (n) {
725 case c_offset_V: // spread_rate
726 return m_usesLambda;
727 case c_offset_L: // lambda
728 return m_usesLambda;
729 case c_offset_E: // eField
730 return false;
731 default:
732 return true;
733 }
734}
735
737{
738 AnyMap state = Domain1D::getMeta();
739 state["transport-model"] = m_trans->transportModel();
740
741 state["phase"]["name"] = m_thermo->name();
742 AnyValue source = m_thermo->input().getMetadata("filename");
743 state["phase"]["source"] = source.empty() ? "<unknown>" : source.asString();
744
745 state["radiation-enabled"] = m_do_radiation;
746 if (m_do_radiation) {
747 state["emissivity-left"] = m_epsilon_left;
748 state["emissivity-right"] = m_epsilon_right;
749 }
750
751 set<bool> energy_flags(m_do_energy.begin(), m_do_energy.end());
752 if (energy_flags.size() == 1) {
753 state["energy-enabled"] = m_do_energy[0];
754 } else {
755 state["energy-enabled"] = m_do_energy;
756 }
757
758 state["Soret-enabled"] = m_do_soret;
759
760 set<bool> species_flags(m_do_species.begin(), m_do_species.end());
761 if (species_flags.size() == 1) {
762 state["species-enabled"] = m_do_species[0];
763 } else {
764 for (size_t k = 0; k < m_nsp; k++) {
765 state["species-enabled"][m_thermo->speciesName(k)] = m_do_species[k];
766 }
767 }
768
769 state["refine-criteria"]["ratio"] = m_refiner->maxRatio();
770 state["refine-criteria"]["slope"] = m_refiner->maxDelta();
771 state["refine-criteria"]["curve"] = m_refiner->maxSlope();
772 state["refine-criteria"]["prune"] = m_refiner->prune();
773 state["refine-criteria"]["grid-min"] = m_refiner->gridMin();
774 state["refine-criteria"]["max-points"] =
775 static_cast<long int>(m_refiner->maxPoints());
776
777 if (m_zfixed != Undef) {
778 state["fixed-point"]["location"] = m_zfixed;
779 state["fixed-point"]["temperature"] = m_tfixed;
780 }
781
782 return state;
783}
784
785shared_ptr<SolutionArray> StFlow::asArray(const double* soln) const
786{
787 auto arr = SolutionArray::create(
788 m_solution, static_cast<int>(nPoints()), getMeta());
789 arr->addExtra("grid", false); // leading entry
790 AnyValue value;
791 value = m_z;
792 arr->setComponent("grid", value);
793 vector<double> data(nPoints());
794 for (size_t i = 0; i < nComponents(); i++) {
795 if (componentActive(i)) {
796 auto name = componentName(i);
797 for (size_t j = 0; j < nPoints(); j++) {
798 data[j] = soln[index(i, j)];
799 }
800 if (!arr->hasComponent(name)) {
801 arr->addExtra(name, componentIndex(name) > c_offset_Y);
802 }
803 value = data;
804 arr->setComponent(name, value);
805 }
806 }
807 value = m_rho;
808 arr->setComponent("D", value); // use density rather than pressure
809
810 if (m_do_radiation) {
811 arr->addExtra("radiative-heat-loss", true); // add at end
812 value = m_qdotRadiation;
813 arr->setComponent("radiative-heat-loss", value);
814 }
815
816 return arr;
817}
818
819void StFlow::fromArray(SolutionArray& arr, double* soln)
820{
821 Domain1D::setMeta(arr.meta());
822 arr.setLoc(0);
823 auto phase = arr.thermo();
824 m_press = phase->pressure();
825
826 const auto grid = arr.getComponent("grid").as<vector<double>>();
827 setupGrid(nPoints(), &grid[0]);
828
829 for (size_t i = 0; i < nComponents(); i++) {
830 if (!componentActive(i)) {
831 continue;
832 }
833 string name = componentName(i);
834 if (arr.hasComponent(name)) {
835 const vector<double> data = arr.getComponent(name).as<vector<double>>();
836 for (size_t j = 0; j < nPoints(); j++) {
837 soln[index(i,j)] = data[j];
838 }
839 } else {
840 warn_user("StFlow::fromArray", "Saved state does not contain values for "
841 "component '{}' in domain '{}'.", name, id());
842 }
843 }
844
845 updateProperties(npos, soln + loc(), 0, m_points - 1);
846 setMeta(arr.meta());
847}
848
849string StFlow::flowType() const {
850 warn_deprecated("StFlow::flowType",
851 "To be removed after Cantera 3.0; superseded by 'type'.");
852 if (m_type == cFreeFlow) {
853 return "Free Flame";
854 } else if (m_type == cAxisymmetricStagnationFlow) {
855 return "Axisymmetric Stagnation";
856 } else {
857 throw CanteraError("StFlow::flowType", "Unknown value for 'm_type'");
858 }
859}
860
861void StFlow::setMeta(const AnyMap& state)
862{
863 if (state.hasKey("energy-enabled")) {
864 const AnyValue& ee = state["energy-enabled"];
865 if (ee.isScalar()) {
866 m_do_energy.assign(nPoints(), ee.asBool());
867 } else {
868 m_do_energy = ee.asVector<bool>(nPoints());
869 }
870 }
871
872 setTransportModel(state.getString("transport-model", "mixture-averaged"));
873
874 if (state.hasKey("Soret-enabled")) {
875 m_do_soret = state["Soret-enabled"].asBool();
876 }
877
878 if (state.hasKey("species-enabled")) {
879 const AnyValue& se = state["species-enabled"];
880 if (se.isScalar()) {
881 m_do_species.assign(m_thermo->nSpecies(), se.asBool());
882 } else {
883 m_do_species = se.asVector<bool>(m_thermo->nSpecies());
884 }
885 }
886
887 if (state.hasKey("radiation-enabled")) {
888 m_do_radiation = state["radiation-enabled"].asBool();
889 if (m_do_radiation) {
890 m_epsilon_left = state["emissivity-left"].asDouble();
891 m_epsilon_right = state["emissivity-right"].asDouble();
892 }
893 }
894
895 if (state.hasKey("refine-criteria")) {
896 const AnyMap& criteria = state["refine-criteria"].as<AnyMap>();
897 double ratio = criteria.getDouble("ratio", m_refiner->maxRatio());
898 double slope = criteria.getDouble("slope", m_refiner->maxDelta());
899 double curve = criteria.getDouble("curve", m_refiner->maxSlope());
900 double prune = criteria.getDouble("prune", m_refiner->prune());
901 m_refiner->setCriteria(ratio, slope, curve, prune);
902
903 if (criteria.hasKey("grid-min")) {
904 m_refiner->setGridMin(criteria["grid-min"].asDouble());
905 }
906 if (criteria.hasKey("max-points")) {
907 m_refiner->setMaxPoints(criteria["max-points"].asInt());
908 }
909 }
910
911 if (state.hasKey("fixed-point")) {
912 m_zfixed = state["fixed-point"]["location"].asDouble();
913 m_tfixed = state["fixed-point"]["temperature"].asDouble();
914 }
915}
916
917void StFlow::solveEnergyEqn(size_t j)
918{
919 bool changed = false;
920 if (j == npos) {
921 for (size_t i = 0; i < m_points; i++) {
922 if (!m_do_energy[i]) {
923 changed = true;
924 }
925 m_do_energy[i] = true;
926 }
927 } else {
928 if (!m_do_energy[j]) {
929 changed = true;
930 }
931 m_do_energy[j] = true;
932 }
933 m_refiner->setActive(c_offset_U, true);
934 m_refiner->setActive(c_offset_V, true);
935 m_refiner->setActive(c_offset_T, true);
936 if (changed) {
938 }
939}
940
942{
943 throw NotImplementedError("StFlow::getSolvingStage",
944 "Not used by '{}' objects.", type());
945}
946
947void StFlow::setSolvingStage(const size_t stage)
948{
949 throw NotImplementedError("StFlow::setSolvingStage",
950 "Not used by '{}' objects.", type());
951}
952
954{
955 throw NotImplementedError("StFlow::solveElectricField",
956 "Not used by '{}' objects.", type());
957}
958
960{
961 throw NotImplementedError("StFlow::fixElectricField",
962 "Not used by '{}' objects.", type());
963}
964
965bool StFlow::doElectricField(size_t j) const
966{
967 throw NotImplementedError("StFlow::doElectricField",
968 "Not used by '{}' objects.", type());
969}
970
971void StFlow::setBoundaryEmissivities(double e_left, double e_right)
972{
973 if (e_left < 0 || e_left > 1) {
974 throw CanteraError("StFlow::setBoundaryEmissivities",
975 "The left boundary emissivity must be between 0.0 and 1.0!");
976 } else if (e_right < 0 || e_right > 1) {
977 throw CanteraError("StFlow::setBoundaryEmissivities",
978 "The right boundary emissivity must be between 0.0 and 1.0!");
979 } else {
980 m_epsilon_left = e_left;
981 m_epsilon_right = e_right;
982 }
983}
984
985void StFlow::fixTemperature(size_t j)
986{
987 bool changed = false;
988 if (j == npos) {
989 for (size_t i = 0; i < m_points; i++) {
990 if (m_do_energy[i]) {
991 changed = true;
992 }
993 m_do_energy[i] = false;
994 }
995 } else {
996 if (m_do_energy[j]) {
997 changed = true;
998 }
999 m_do_energy[j] = false;
1000 }
1001 m_refiner->setActive(c_offset_U, false);
1002 m_refiner->setActive(c_offset_V, false);
1003 m_refiner->setActive(c_offset_T, false);
1004 if (changed) {
1005 needJacUpdate();
1006 }
1007}
1008
1009void StFlow::evalRightBoundary(double* x, double* rsd, int* diag, double rdt)
1010{
1011 size_t j = m_points - 1;
1012
1013 // the boundary object connected to the right of this one may modify or
1014 // replace these equations. The default boundary conditions are zero u, V,
1015 // and T, and zero diffusive flux for all species.
1016
1017 rsd[index(c_offset_V,j)] = V(x,j);
1018 diag[index(c_offset_V,j)] = 0;
1019 double sum = 0.0;
1020 // set residual of poisson's equ to zero
1021 rsd[index(c_offset_E, j)] = x[index(c_offset_E, j)];
1022 for (size_t k = 0; k < m_nsp; k++) {
1023 sum += Y(x,k,j);
1024 rsd[index(k+c_offset_Y,j)] = m_flux(k,j-1) + rho_u(x,j)*Y(x,k,j);
1025 }
1026 rsd[index(c_offset_Y + rightExcessSpecies(), j)] = 1.0 - sum;
1027 diag[index(c_offset_Y + rightExcessSpecies(), j)] = 0;
1028 if (m_usesLambda) {
1029 rsd[index(c_offset_U, j)] = rho_u(x, j);
1030 } else {
1031 rsd[index(c_offset_U, j)] = rho_u(x, j) - rho_u(x, j-1);
1032 }
1033
1034 rsd[index(c_offset_L, j)] = lambda(x, j) - lambda(x, j-1);
1035 diag[index(c_offset_L, j)] = 0;
1036 rsd[index(c_offset_T, j)] = T(x, j);
1037}
1038
1039void StFlow::evalContinuity(size_t j, double* x, double* rsd, int* diag, double rdt)
1040{
1041 //algebraic constraint
1042 diag[index(c_offset_U, j)] = 0;
1043 //----------------------------------------------
1044 // Continuity equation
1045 //
1046 // d(\rho u)/dz + 2\rho V = 0
1047 //----------------------------------------------
1048 if (m_usesLambda) {
1049 // Note that this propagates the mass flow rate information to the left
1050 // (j+1 -> j) from the value specified at the right boundary. The
1051 // lambda information propagates in the opposite direction.
1052 rsd[index(c_offset_U,j)] =
1053 -(rho_u(x,j+1) - rho_u(x,j))/m_dz[j]
1054 -(density(j+1)*V(x,j+1) + density(j)*V(x,j));
1055 } else if (m_isFree) {
1056 // terms involving V are zero as V=0 by definition
1057 if (grid(j) > m_zfixed) {
1058 rsd[index(c_offset_U,j)] =
1059 - (rho_u(x,j) - rho_u(x,j-1))/m_dz[j-1];
1060 } else if (grid(j) == m_zfixed) {
1061 if (m_do_energy[j]) {
1062 rsd[index(c_offset_U,j)] = (T(x,j) - m_tfixed);
1063 } else {
1064 rsd[index(c_offset_U,j)] = (rho_u(x,j)
1065 - m_rho[0]*0.3); // why 0.3?
1066 }
1067 } else if (grid(j) < m_zfixed) {
1068 rsd[index(c_offset_U,j)] =
1069 - (rho_u(x,j+1) - rho_u(x,j))/m_dz[j];
1070 }
1071 } else {
1072 // unstrained with fixed mass flow rate
1073 rsd[index(c_offset_U, j)] = rho_u(x, j) - rho_u(x, j - 1);
1074 }
1075}
1076
1077void StFlow::grad_hk(const double* x, size_t j)
1078{
1079 for(size_t k = 0; k < m_nsp; k++) {
1080 if (u(x, j) > 0.0) {
1081 m_dhk_dz(k,j) = (m_hk(k,j) - m_hk(k,j-1)) / m_dz[j - 1];
1082 }
1083 else {
1084 m_dhk_dz(k,j) = (m_hk(k,j+1) - m_hk(k,j)) / m_dz[j];
1085 }
1086 }
1087}
1088
1089} // namespace
Header file defining class TransportFactory (see TransportFactory)
Headers for the Transport object, which is the virtual base class for all transport property evaluato...
const AnyValue & getMetadata(const string &key) const
Get a value from the metadata applicable to the AnyMap tree containing this node.
Definition AnyMap.cpp:580
A map of string keys to values whose type can vary at runtime.
Definition AnyMap.h:427
double getDouble(const string &key, double default_) const
If key exists, return it as a double, otherwise return default_.
Definition AnyMap.cpp:1520
bool hasKey(const string &key) const
Returns true if the map contains an item named key.
Definition AnyMap.cpp:1423
const string & getString(const string &key, const string &default_) const
If key exists, return it as a string, otherwise return default_.
Definition AnyMap.cpp:1530
A wrapper for a variable whose type is determined at runtime.
Definition AnyMap.h:86
const string & asString() const
Return the held value, if it is a string.
Definition AnyMap.cpp:739
bool & asBool()
Return the held value, if it is a bool.
Definition AnyMap.cpp:871
bool empty() const
Return boolean indicating whether AnyValue is empty.
Definition AnyMap.cpp:647
bool isScalar() const
Returns true if the held value is a scalar type (such as double, long int, string,...
Definition AnyMap.cpp:651
const vector< T > & asVector(size_t nMin=npos, size_t nMax=npos) const
Return the held value, if it is a vector of type T.
Definition AnyMap.inl.h:109
const T & as() const
Get the value of this key as the specified type.
Definition AnyMap.inl.h:16
double * ptrColumn(size_t j)
Return a pointer to the top of column j, columns are contiguous in memory.
Definition Array.h:235
virtual void resize(size_t n, size_t m, double v=0.0)
Resize the array, and fill the new entries with 'v'.
Definition Array.cpp:47
Base class for exceptions thrown by Cantera classes.
Base class for one-dimensional domains.
Definition Domain1D.h:41
size_t lastPoint() const
The index of the last (that is, right-most) grid point belonging to this domain.
Definition Domain1D.h:434
shared_ptr< Solution > m_solution
Composite thermo/kinetics/transport handler.
Definition Domain1D.h:609
size_t nComponents() const
Number of components at each grid point.
Definition Domain1D.h:160
virtual void setMeta(const AnyMap &meta)
Retrieve meta data.
Definition Domain1D.cpp:172
size_t nPoints() const
Number of grid points in this domain.
Definition Domain1D.h:182
virtual void resize(size_t nv, size_t np)
Resize the domain to have nv components and np grid points.
Definition Domain1D.cpp:33
size_t m_points
Number of grid points.
Definition Domain1D.h:578
string m_id
Identity tag for the domain.
Definition Domain1D.h:602
size_t firstPoint() const
The index of the first (that is, left-most) grid point belonging to this domain.
Definition Domain1D.h:426
void needJacUpdate()
Set this if something has changed in the governing equations (for example, the value of a constant ha...
Definition Domain1D.cpp:102
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:418
virtual AnyMap getMeta() const
Retrieve meta data.
Definition Domain1D.cpp:110
virtual void show(std::ostream &s, const double *x)
Print the solution.
Definition Domain1D.h:500
Public interface for kinetics managers.
Definition Kinetics.h:126
An error indicating that an unimplemented function has been called.
size_t nSpecies() const
Returns the number of species in the phase.
Definition Phase.h:245
virtual void setMassFractions_NoNorm(const double *const y)
Set the mass fractions to the specified values without normalizing.
Definition Phase.cpp:370
double temperature() const
Temperature (K).
Definition Phase.h:662
virtual void setPressure(double p)
Set the internally stored pressure (Pa) at constant temperature and composition.
Definition Phase.h:721
double meanMolecularWeight() const
The mean molecular weight. Units: (kg/kmol)
Definition Phase.h:760
string speciesName(size_t k) const
Name of the species with index k.
Definition Phase.cpp:151
const vector< double > & molecularWeights() const
Return a const reference to the internal vector of molecular weights.
Definition Phase.cpp:501
size_t speciesIndex(const string &name) const
Returns the index of a species named 'name' within the Phase object.
Definition Phase.cpp:138
virtual double density() const
Density (kg/m^3).
Definition Phase.h:687
virtual void setTemperature(double temp)
Set the internally stored temperature of the phase (K).
Definition Phase.h:728
virtual void setMassFractions(const double *const y)
Set the mass fractions to the specified values and normalize them.
Definition Phase.cpp:356
void getMassFractions(double *const y) const
Get the species mass fractions.
Definition Phase.cpp:584
virtual double pressure() const
Return the thermodynamic pressure (Pa).
Definition Phase.h:680
string name() const
Return the name of the phase.
Definition Phase.cpp:20
A container class holding arrays of state information.
void setLoc(int loc, bool restore=true)
Update the buffered location used to access SolutionArray entries.
AnyValue getComponent(const string &name) const
Retrieve a component of the SolutionArray by name.
bool hasComponent(const string &name) const
Check whether SolutionArray contains a component.
AnyMap & meta()
SolutionArray meta data.
shared_ptr< ThermoPhase > thermo()
Retrieve associated ThermoPhase object.
static shared_ptr< SolutionArray > create(const shared_ptr< Solution > &sol, int size=0, const AnyMap &meta={})
Instantiate a new SolutionArray reference.
static shared_ptr< Solution > create()
Create an empty Solution object.
Definition Solution.h:54
This class represents 1D flow domains that satisfy the one-dimensional similarity solution for chemic...
Definition StFlow.h:45
virtual void evalResidual(double *x, double *rsd, int *diag, double rdt, size_t jmin, size_t jmax)
Evaluate the residual function.
Definition StFlow.cpp:404
virtual void evalRightBoundary(double *x, double *res, int *diag, double rdt)
Evaluate all residual components at the right boundary.
Definition StFlow.cpp:1009
virtual void evalContinuity(size_t j, double *x, double *r, int *diag, double rdt)
Evaluate the residual corresponding to the continuity equation at all interior grid points.
Definition StFlow.cpp:1039
size_t m_kExcessLeft
Index of species with a large mass fraction at each boundary, for which the mass fraction may be calc...
Definition StFlow.h:550
void setMeta(const AnyMap &state) override
Retrieve meta data.
Definition StFlow.cpp:861
void setTransportModel(const string &trans)
Set the transport model.
Definition StFlow.cpp:237
void setTransport(shared_ptr< Transport > trans) override
Set transport model to existing instance.
Definition StFlow.cpp:161
void setKinetics(shared_ptr< Kinetics > kin) override
Set the kinetics manager.
Definition StFlow.cpp:143
void resetBadValues(double *xg) override
When called, this function should reset "bad" values in the state vector such as negative species con...
Definition StFlow.cpp:227
virtual string flowType() const
Return the type of flow domain being represented, either "Free Flame" or "Axisymmetric Stagnation".
Definition StFlow.cpp:849
size_t rightExcessSpecies() const
Index of the species on the right boundary with the largest mass fraction.
Definition StFlow.h:345
vector< double > m_qdotRadiation
radiative heat loss vector
Definition StFlow.h:540
void updateThermo(const double *x, size_t j0, size_t j1)
Update the thermodynamic properties from point j0 to point j1 (inclusive), based on solution x.
Definition StFlow.h:377
void resize(size_t components, size_t points) override
Change the grid size. Called after grid refinement.
Definition StFlow.cpp:186
StFlow(ThermoPhase *ph=0, size_t nsp=1, size_t points=1)
Create a new flow domain.
Definition StFlow.cpp:19
void setBoundaryEmissivities(double e_left, double e_right)
Set the emissivities for the boundary values.
Definition StFlow.cpp:971
string type() const override
String indicating the domain implemented.
Definition StFlow.cpp:128
shared_ptr< SolutionArray > asArray(const double *soln) const override
Save the state of this domain as a SolutionArray.
Definition StFlow.cpp:785
size_t componentIndex(const string &name) const override
index of component with name name.
Definition StFlow.cpp:699
void setGas(const double *x, size_t j)
Set the gas object state to be consistent with the solution at point j.
Definition StFlow.cpp:280
double m_tfixed
Temperature at the point used to fix the flame location.
Definition StFlow.h:566
virtual bool componentActive(size_t n) const
Returns true if the specified component is an active part of the solver state.
Definition StFlow.cpp:722
Array2D m_hk
Array of size m_nsp by m_points for saving molar enthalpies.
Definition StFlow.h:508
virtual bool doElectricField(size_t j) const
Retrieve flag indicating whether electric field is solved or not (used by IonFlow specialization)
Definition StFlow.cpp:965
void eval(size_t j, double *x, double *r, integer *mask, double rdt) override
Evaluate the residual function for axisymmetric stagnation flow.
Definition StFlow.cpp:353
void setupGrid(size_t n, const double *z) override
called to set up initial grid, and after grid refinement
Definition StFlow.cpp:212
size_t leftExcessSpecies() const
Index of the species on the left boundary with the largest mass fraction.
Definition StFlow.h:340
Array2D m_dhk_dz
Array of size m_nsp by m_points-1 for saving enthalpy fluxes.
Definition StFlow.h:511
double m_zfixed
Location of the point where temperature is fixed.
Definition StFlow.h:563
void _finalize(const double *x) override
In some cases, a domain may need to set parameters that depend on the initial solution estimate.
Definition StFlow.cpp:306
virtual size_t getSolvingStage() const
Get the solving stage (used by IonFlow specialization)
Definition StFlow.cpp:941
size_t m_nsp
Number of species in the mechanism.
Definition StFlow.h:516
void getWdot(double *x, size_t j)
Write the net production rates at point j into array m_wdot
Definition StFlow.h:358
void fromArray(SolutionArray &arr, double *soln) override
Restore the solution for this domain from a SolutionArray.
Definition StFlow.cpp:819
virtual bool fixed_mdot()
Definition StFlow.cpp:300
AnyMap getMeta() const override
Retrieve meta data.
Definition StFlow.cpp:736
virtual void updateDiffFluxes(const double *x, size_t j0, size_t j1)
Update the diffusive mass fluxes.
Definition StFlow.cpp:635
string componentName(size_t n) const override
Name of the nth component. May be overloaded.
Definition StFlow.cpp:677
void setGasAtMidpoint(const double *x, size_t j)
Set the gas state to be consistent with the solution at the midpoint between j and j + 1.
Definition StFlow.cpp:288
virtual void grad_hk(const double *x, size_t j)
Get the gradient of species specific molar enthalpies.
Definition StFlow.cpp:1077
string transportModel() const
Retrieve transport model.
Definition StFlow.cpp:248
virtual void updateProperties(size_t jg, double *x, size_t jmin, size_t jmax)
Update the properties (thermo, transport, and diffusion flux).
Definition StFlow.cpp:380
void setThermo(ThermoPhase &th)
Set the thermo manager.
Definition StFlow.cpp:138
void show(const double *x) override
Print the solution.
Definition StFlow.cpp:618
virtual void setSolvingStage(const size_t stage)
Solving stage mode for handling ionized species (used by IonFlow specialization)
Definition StFlow.cpp:947
void setPressure(double p)
Set the pressure.
Definition StFlow.h:128
virtual void fixElectricField(size_t j=npos)
Set to fix voltage in a point (used by IonFlow specialization)
Definition StFlow.cpp:959
virtual void updateTransport(double *x, size_t j0, size_t j1)
Update the transport properties at grid points in the range from j0 to j1, based on solution x.
Definition StFlow.cpp:588
virtual void solveElectricField(size_t j=npos)
Set to solve electric field in a point (used by IonFlow specialization)
Definition StFlow.cpp:953
void _getInitialSoln(double *x) override
Write the initial solution estimate into array x.
Definition StFlow.cpp:271
vector< size_t > m_kRadiating
Indices within the ThermoPhase of the radiating species.
Definition StFlow.h:528
double T_fixed(size_t j) const
The fixed temperature value at point j.
Definition StFlow.h:160
bool m_do_radiation
flag for the radiative heat loss
Definition StFlow.h:537
Base class for a phase with thermodynamic properties.
virtual double maxTemp(size_t k=npos) const
Maximum temperature for which the thermodynamic data for the species are valid.
const AnyMap & input() const
Access input data associated with the phase description.
Base class for transport property managers.
Definition Transport.h:146
virtual void getThermalDiffCoeffs(double *const dt)
Return a vector of Thermal diffusion coefficients [kg/m/sec].
Definition Transport.h:595
virtual string transportModel() const
Identifies the model represented by this Transport object.
Definition Transport.h:173
virtual void getMixDiffCoeffs(double *const d)
Returns a vector of mixture averaged diffusion coefficients.
Definition Transport.h:639
virtual double thermalConductivity()
Returns the mixture thermal conductivity in W/m/K.
Definition Transport.h:318
virtual double viscosity()
The viscosity in Pa-s.
Definition Transport.h:230
virtual void getMultiDiffCoeffs(const size_t ld, double *const d)
Return the Multicomponent diffusion coefficients. Units: [m^2/s].
Definition Transport.h:624
Header for a file containing miscellaneous numerical functions.
This file contains definitions for utility functions and text for modules, inputfiles and logging,...
void writelog(const string &fmt, const Args &... args)
Write a formatted message to the screen.
Definition global.h:175
double linearInterp(double x, const vector< double > &xpts, const vector< double > &fpts)
Linearly interpolate a function defined on a discrete grid.
Definition funcs.cpp:13
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
void warn_user(const string &method, const string &msg, const Args &... args)
Print a user warning raised from method as CanteraWarning.
Definition global.h:267
Namespace for the Cantera kernel.
Definition AnyMap.cpp:564
const size_t npos
index returned by functions to indicate "no position"
Definition ct_defs.h:195
const double Undef
Fairly random number to be used to initialize variables against to see if they are subsequently defin...
Definition ct_defs.h:164
@ c_offset_U
axial velocity
Definition StFlow.h:25
@ c_offset_L
(1/r)dP/dr
Definition StFlow.h:28
@ c_offset_V
strain rate
Definition StFlow.h:26
@ c_offset_E
electric poisson's equation
Definition StFlow.h:29
@ c_offset_Y
mass fractions
Definition StFlow.h:30
@ c_offset_T
temperature
Definition StFlow.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:1926