Cantera  2.5.1
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 
6 #include "cantera/oneD/StFlow.h"
7 #include "cantera/base/ctml.h"
10 
11 using namespace std;
12 
13 namespace Cantera
14 {
15 
16 StFlow::StFlow(ThermoPhase* ph, size_t nsp, size_t points) :
17  Domain1D(nsp+c_offset_Y, points),
18  m_press(-1.0),
19  m_nsp(nsp),
20  m_thermo(0),
21  m_kin(0),
22  m_trans(0),
23  m_epsilon_left(0.0),
24  m_epsilon_right(0.0),
25  m_do_soret(false),
26  m_do_multicomponent(false),
27  m_do_radiation(false),
28  m_kExcessLeft(0),
29  m_kExcessRight(0),
30  m_zfixed(Undef),
31  m_tfixed(-1.)
32 {
33  if (ph->type() == "IdealGas") {
34  m_thermo = static_cast<IdealGasPhase*>(ph);
35  } else {
36  throw CanteraError("StFlow::StFlow",
37  "Unsupported phase type: need 'IdealGasPhase'");
38  }
39  m_type = cFlowType;
40  m_points = points;
41 
42  if (ph == 0) {
43  return; // used to create a dummy object
44  }
45 
46  size_t nsp2 = m_thermo->nSpecies();
47  if (nsp2 != m_nsp) {
48  m_nsp = nsp2;
49  Domain1D::resize(m_nsp+c_offset_Y, points);
50  }
51 
52  // make a local copy of the species molecular weight vector
53  m_wt = m_thermo->molecularWeights();
54 
55  // the species mass fractions are the last components in the solution
56  // vector, so the total number of components is the number of species
57  // plus the offset of the first mass fraction.
58  m_nv = c_offset_Y + m_nsp;
59 
60  // enable all species equations by default
61  m_do_species.resize(m_nsp, true);
62 
63  // but turn off the energy equation at all points
64  m_do_energy.resize(m_points,false);
65 
66  m_diff.resize(m_nsp*m_points);
67  m_multidiff.resize(m_nsp*m_nsp*m_points);
68  m_flux.resize(m_nsp,m_points);
69  m_wdot.resize(m_nsp,m_points, 0.0);
70  m_ybar.resize(m_nsp);
71  m_qdotRadiation.resize(m_points, 0.0);
72 
73  //-------------- default solution bounds --------------------
74  setBounds(0, -1e20, 1e20); // no bounds on u
75  setBounds(1, -1e20, 1e20); // V
76  setBounds(2, 200.0, 2*m_thermo->maxTemp()); // temperature bounds
77  setBounds(3, -1e20, 1e20); // lambda should be negative
78 
79  // mass fraction bounds
80  for (size_t k = 0; k < m_nsp; k++) {
81  setBounds(c_offset_Y+k, -1.0e-7, 1.0e5);
82  }
83 
84  //-------------------- grid refinement -------------------------
85  m_refiner->setActive(c_offset_U, false);
86  m_refiner->setActive(c_offset_V, false);
87  m_refiner->setActive(c_offset_T, false);
88  m_refiner->setActive(c_offset_L, false);
89 
90  vector_fp gr;
91  for (size_t ng = 0; ng < m_points; ng++) {
92  gr.push_back(1.0*ng/m_points);
93  }
94  setupGrid(m_points, gr.data());
95 
96  // Find indices for radiating species
97  m_kRadiating.resize(2, npos);
98  m_kRadiating[0] = m_thermo->speciesIndex("CO2");
99  m_kRadiating[1] = m_thermo->speciesIndex("H2O");
100 }
101 
102 void StFlow::resize(size_t ncomponents, size_t points)
103 {
104  Domain1D::resize(ncomponents, points);
105  m_rho.resize(m_points, 0.0);
106  m_wtm.resize(m_points, 0.0);
107  m_cp.resize(m_points, 0.0);
108  m_visc.resize(m_points, 0.0);
109  m_tcon.resize(m_points, 0.0);
110 
111  m_diff.resize(m_nsp*m_points);
112  if (m_do_multicomponent) {
113  m_multidiff.resize(m_nsp*m_nsp*m_points);
114  m_dthermal.resize(m_nsp, m_points, 0.0);
115  }
116  m_flux.resize(m_nsp,m_points);
117  m_wdot.resize(m_nsp,m_points, 0.0);
118  m_do_energy.resize(m_points,false);
119  m_qdotRadiation.resize(m_points, 0.0);
120  m_fixedtemp.resize(m_points);
121 
122  m_dz.resize(m_points-1);
123  m_z.resize(m_points);
124 }
125 
126 void StFlow::setupGrid(size_t n, const doublereal* z)
127 {
128  resize(m_nv, n);
129 
130  m_z[0] = z[0];
131  for (size_t j = 1; j < m_points; j++) {
132  if (z[j] <= z[j-1]) {
133  throw CanteraError("StFlow::setupGrid",
134  "grid points must be monotonically increasing");
135  }
136  m_z[j] = z[j];
137  m_dz[j-1] = m_z[j] - m_z[j-1];
138  }
139 }
140 
141 void StFlow::resetBadValues(double* xg)
142 {
143  double* x = xg + loc();
144  for (size_t j = 0; j < m_points; j++) {
145  double* Y = x + m_nv*j + c_offset_Y;
146  m_thermo->setMassFractions(Y);
147  m_thermo->getMassFractions(Y);
148  }
149 }
150 
152 {
153  m_trans = &trans;
154  m_do_multicomponent = (m_trans->transportType() == "Multi");
155 
156  m_diff.resize(m_nsp*m_points);
157  if (m_do_multicomponent) {
158  m_multidiff.resize(m_nsp*m_nsp*m_points);
159  m_dthermal.resize(m_nsp, m_points, 0.0);
160  }
161 }
162 
163 void StFlow::_getInitialSoln(double* x)
164 {
165  for (size_t j = 0; j < m_points; j++) {
166  T(x,j) = m_thermo->temperature();
167  m_thermo->getMassFractions(&Y(x, 0, j));
168  }
169 }
170 
171 void StFlow::setGas(const doublereal* x, size_t j)
172 {
173  m_thermo->setTemperature(T(x,j));
174  const doublereal* yy = x + m_nv*j + c_offset_Y;
175  m_thermo->setMassFractions_NoNorm(yy);
176  m_thermo->setPressure(m_press);
177 }
178 
179 void StFlow::setGasAtMidpoint(const doublereal* x, size_t j)
180 {
181  m_thermo->setTemperature(0.5*(T(x,j)+T(x,j+1)));
182  const doublereal* yyj = x + m_nv*j + c_offset_Y;
183  const doublereal* yyjp = x + m_nv*(j+1) + c_offset_Y;
184  for (size_t k = 0; k < m_nsp; k++) {
185  m_ybar[k] = 0.5*(yyj[k] + yyjp[k]);
186  }
187  m_thermo->setMassFractions_NoNorm(m_ybar.data());
188  m_thermo->setPressure(m_press);
189 }
190 
191 void StFlow::_finalize(const doublereal* x)
192 {
193  if (!m_do_multicomponent && m_do_soret) {
194  throw CanteraError("StFlow::_finalize",
195  "Thermal diffusion (the Soret effect) is enabled, and requires "
196  "using a multicomponent transport model.");
197  }
198 
199  size_t nz = m_zfix.size();
200  bool e = m_do_energy[0];
201  for (size_t j = 0; j < m_points; j++) {
202  if (e || nz == 0) {
203  m_fixedtemp[j] = T(x, j);
204  } else {
205  double zz = (z(j) - z(0))/(z(m_points - 1) - z(0));
206  double tt = linearInterp(zz, m_zfix, m_tfix);
207  m_fixedtemp[j] = tt;
208  }
209  }
210  if (e) {
211  solveEnergyEqn();
212  }
213 
214  if (domainType() == cFreeFlow) {
215  // If the domain contains the temperature fixed point, make sure that it
216  // is correctly set. This may be necessary when the grid has been modified
217  // externally.
218  if (m_tfixed != Undef) {
219  for (size_t j = 0; j < m_points; j++) {
220  if (z(j) == m_zfixed) {
221  return; // fixed point is already set correctly
222  }
223  }
224 
225  for (size_t j = 0; j < m_points - 1; j++) {
226  // Find where the temperature profile crosses the current
227  // fixed temperature.
228  if ((T(x, j) - m_tfixed) * (T(x, j+1) - m_tfixed) <= 0.0) {
229  m_tfixed = T(x, j+1);
230  m_zfixed = z(j+1);
231  return;
232  }
233  }
234  }
235  }
236 }
237 
238 void StFlow::eval(size_t jg, doublereal* xg,
239  doublereal* rg, integer* diagg, doublereal rdt)
240 {
241  // if evaluating a Jacobian, and the global point is outside the domain of
242  // influence for this domain, then skip evaluating the residual
243  if (jg != npos && (jg + 1 < firstPoint() || jg > lastPoint() + 1)) {
244  return;
245  }
246 
247  // start of local part of global arrays
248  doublereal* x = xg + loc();
249  doublereal* rsd = rg + loc();
250  integer* diag = diagg + loc();
251 
252  size_t jmin, jmax;
253  if (jg == npos) { // evaluate all points
254  jmin = 0;
255  jmax = m_points - 1;
256  } else { // evaluate points for Jacobian
257  size_t jpt = (jg == 0) ? 0 : jg - firstPoint();
258  jmin = std::max<size_t>(jpt, 1) - 1;
259  jmax = std::min(jpt+1,m_points-1);
260  }
261 
262  updateProperties(jg, x, jmin, jmax);
263  evalResidual(x, rsd, diag, rdt, jmin, jmax);
264 }
265 
266 void StFlow::updateProperties(size_t jg, double* x, size_t jmin, size_t jmax)
267 {
268  // properties are computed for grid points from j0 to j1
269  size_t j0 = std::max<size_t>(jmin, 1) - 1;
270  size_t j1 = std::min(jmax+1,m_points-1);
271 
272  updateThermo(x, j0, j1);
273  if (jg == npos || m_force_full_update) {
274  // update transport properties only if a Jacobian is not being
275  // evaluated, or if specifically requested
276  updateTransport(x, j0, j1);
277  }
278  if (jg == npos) {
279  double* Yleft = x + index(c_offset_Y, jmin);
280  m_kExcessLeft = distance(Yleft, max_element(Yleft, Yleft + m_nsp));
281  double* Yright = x + index(c_offset_Y, jmax);
282  m_kExcessRight = distance(Yright, max_element(Yright, Yright + m_nsp));
283  }
284 
285  // update the species diffusive mass fluxes whether or not a
286  // Jacobian is being evaluated
287  updateDiffFluxes(x, j0, j1);
288 }
289 
290 void StFlow::evalResidual(double* x, double* rsd, int* diag,
291  double rdt, size_t jmin, size_t jmax)
292 {
293  //----------------------------------------------------
294  // evaluate the residual equations at all required
295  // grid points
296  //----------------------------------------------------
297 
298  // calculation of qdotRadiation
299 
300  // The simple radiation model used was established by Y. Liu and B. Rogg [Y.
301  // Liu and B. Rogg, Modelling of thermally radiating diffusion flames with
302  // detailed chemistry and transport, EUROTHERM Seminars, 17:114-127, 1991].
303  // This model uses the optically thin limit and the gray-gas approximation
304  // to simply calculate a volume specified heat flux out of the Planck
305  // absorption coefficients, the boundary emissivities and the temperature.
306  // The model considers only CO2 and H2O as radiating species. Polynomial
307  // lines calculate the species Planck coefficients for H2O and CO2. The data
308  // for the lines is taken from the RADCAL program [Grosshandler, W. L.,
309  // RADCAL: A Narrow-Band Model for Radiation Calculations in a Combustion
310  // Environment, NIST technical note 1402, 1993]. The coefficients for the
311  // polynomials are taken from [http://www.sandia.gov/TNF/radiation.html].
312 
313  if (m_do_radiation) {
314  // variable definitions for the Planck absorption coefficient and the
315  // radiation calculation:
316  doublereal k_P_ref = 1.0*OneAtm;
317 
318  // polynomial coefficients:
319  const doublereal c_H2O[6] = {-0.23093, -1.12390, 9.41530, -2.99880,
320  0.51382, -1.86840e-5};
321  const doublereal c_CO2[6] = {18.741, -121.310, 273.500, -194.050,
322  56.310, -5.8169};
323 
324  // calculation of the two boundary values
325  double boundary_Rad_left = m_epsilon_left * StefanBoltz * pow(T(x, 0), 4);
326  double boundary_Rad_right = m_epsilon_right * StefanBoltz * pow(T(x, m_points - 1), 4);
327 
328  // loop over all grid points
329  for (size_t j = jmin; j < jmax; j++) {
330  // helping variable for the calculation
331  double radiative_heat_loss = 0;
332 
333  // calculation of the mean Planck absorption coefficient
334  double k_P = 0;
335  // absorption coefficient for H2O
336  if (m_kRadiating[1] != npos) {
337  double k_P_H2O = 0;
338  for (size_t n = 0; n <= 5; n++) {
339  k_P_H2O += c_H2O[n] * pow(1000 / T(x, j), (double) n);
340  }
341  k_P_H2O /= k_P_ref;
342  k_P += m_press * X(x, m_kRadiating[1], j) * k_P_H2O;
343  }
344  // absorption coefficient for CO2
345  if (m_kRadiating[0] != npos) {
346  double k_P_CO2 = 0;
347  for (size_t n = 0; n <= 5; n++) {
348  k_P_CO2 += c_CO2[n] * pow(1000 / T(x, j), (double) n);
349  }
350  k_P_CO2 /= k_P_ref;
351  k_P += m_press * X(x, m_kRadiating[0], j) * k_P_CO2;
352  }
353 
354  // calculation of the radiative heat loss term
355  radiative_heat_loss = 2 * k_P *(2 * StefanBoltz * pow(T(x, j), 4)
356  - boundary_Rad_left - boundary_Rad_right);
357 
358  // set the radiative heat loss vector
359  m_qdotRadiation[j] = radiative_heat_loss;
360  }
361  }
362 
363  for (size_t j = jmin; j <= jmax; j++) {
364  //----------------------------------------------
365  // left boundary
366  //----------------------------------------------
367 
368  if (j == 0) {
369  // these may be modified by a boundary object
370 
371  // Continuity. This propagates information right-to-left, since
372  // rho_u at point 0 is dependent on rho_u at point 1, but not on
373  // mdot from the inlet.
374  rsd[index(c_offset_U,0)] =
375  -(rho_u(x,1) - rho_u(x,0))/m_dz[0]
376  -(density(1)*V(x,1) + density(0)*V(x,0));
377 
378  // the inlet (or other) object connected to this one will modify
379  // these equations by subtracting its values for V, T, and mdot. As
380  // a result, these residual equations will force the solution
381  // variables to the values for the boundary object
382  rsd[index(c_offset_V,0)] = V(x,0);
383  if (doEnergy(0)) {
384  rsd[index(c_offset_T,0)] = T(x,0);
385  } else {
386  rsd[index(c_offset_T,0)] = T(x,0) - T_fixed(0);
387  }
388  rsd[index(c_offset_L,0)] = -rho_u(x,0);
389 
390  // The default boundary condition for species is zero flux. However,
391  // the boundary object may modify this.
392  double sum = 0.0;
393  for (size_t k = 0; k < m_nsp; k++) {
394  sum += Y(x,k,0);
395  rsd[index(c_offset_Y + k, 0)] =
396  -(m_flux(k,0) + rho_u(x,0)* Y(x,k,0));
397  }
398  rsd[index(c_offset_Y + leftExcessSpecies(), 0)] = 1.0 - sum;
399 
400  // set residual of poisson's equ to zero
401  rsd[index(c_offset_E, 0)] = x[index(c_offset_E, j)];
402  } else if (j == m_points - 1) {
403  evalRightBoundary(x, rsd, diag, rdt);
404  // set residual of poisson's equ to zero
405  rsd[index(c_offset_E, j)] = x[index(c_offset_E, j)];
406  } else { // interior points
407  evalContinuity(j, x, rsd, diag, rdt);
408  // set residual of poisson's equ to zero
409  rsd[index(c_offset_E, j)] = x[index(c_offset_E, j)];
410 
411  //------------------------------------------------
412  // Radial momentum equation
413  //
414  // \rho dV/dt + \rho u dV/dz + \rho V^2
415  // = d(\mu dV/dz)/dz - lambda
416  //-------------------------------------------------
417  rsd[index(c_offset_V,j)]
418  = (shear(x,j) - lambda(x,j) - rho_u(x,j)*dVdz(x,j)
419  - m_rho[j]*V(x,j)*V(x,j))/m_rho[j]
420  - rdt*(V(x,j) - V_prev(j));
421  diag[index(c_offset_V, j)] = 1;
422 
423  //-------------------------------------------------
424  // Species equations
425  //
426  // \rho dY_k/dt + \rho u dY_k/dz + dJ_k/dz
427  // = M_k\omega_k
428  //-------------------------------------------------
429  getWdot(x,j);
430  for (size_t k = 0; k < m_nsp; k++) {
431  double convec = rho_u(x,j)*dYdz(x,k,j);
432  double diffus = 2.0*(m_flux(k,j) - m_flux(k,j-1))
433  / (z(j+1) - z(j-1));
434  rsd[index(c_offset_Y + k, j)]
435  = (m_wt[k]*(wdot(k,j))
436  - convec - diffus)/m_rho[j]
437  - rdt*(Y(x,k,j) - Y_prev(k,j));
438  diag[index(c_offset_Y + k, j)] = 1;
439  }
440 
441  //-----------------------------------------------
442  // energy equation
443  //
444  // \rho c_p dT/dt + \rho c_p u dT/dz
445  // = d(k dT/dz)/dz
446  // - sum_k(\omega_k h_k_ref)
447  // - sum_k(J_k c_p_k / M_k) dT/dz
448  //-----------------------------------------------
449  if (m_do_energy[j]) {
450  setGas(x,j);
451 
452  // heat release term
453  const vector_fp& h_RT = m_thermo->enthalpy_RT_ref();
454  const vector_fp& cp_R = m_thermo->cp_R_ref();
455  double sum = 0.0;
456  double sum2 = 0.0;
457  for (size_t k = 0; k < m_nsp; k++) {
458  double flxk = 0.5*(m_flux(k,j-1) + m_flux(k,j));
459  sum += wdot(k,j)*h_RT[k];
460  sum2 += flxk*cp_R[k]/m_wt[k];
461  }
462  sum *= GasConstant * T(x,j);
463  double dtdzj = dTdz(x,j);
464  sum2 *= GasConstant * dtdzj;
465 
466  rsd[index(c_offset_T, j)] = - m_cp[j]*rho_u(x,j)*dtdzj
467  - divHeatFlux(x,j) - sum - sum2;
468  rsd[index(c_offset_T, j)] /= (m_rho[j]*m_cp[j]);
469  rsd[index(c_offset_T, j)] -= rdt*(T(x,j) - T_prev(j));
470  rsd[index(c_offset_T, j)] -= (m_qdotRadiation[j] / (m_rho[j] * m_cp[j]));
471  diag[index(c_offset_T, j)] = 1;
472  } else {
473  // residual equations if the energy equation is disabled
474  rsd[index(c_offset_T, j)] = T(x,j) - T_fixed(j);
475  diag[index(c_offset_T, j)] = 0;
476  }
477 
478  rsd[index(c_offset_L, j)] = lambda(x,j) - lambda(x,j-1);
479  diag[index(c_offset_L, j)] = 0;
480  }
481  }
482 }
483 
484 void StFlow::updateTransport(doublereal* x, size_t j0, size_t j1)
485 {
486  if (m_do_multicomponent) {
487  for (size_t j = j0; j < j1; j++) {
488  setGasAtMidpoint(x,j);
489  doublereal wtm = m_thermo->meanMolecularWeight();
490  doublereal rho = m_thermo->density();
491  m_visc[j] = (m_dovisc ? m_trans->viscosity() : 0.0);
492  m_trans->getMultiDiffCoeffs(m_nsp, &m_multidiff[mindex(0,0,j)]);
493 
494  // Use m_diff as storage for the factor outside the summation
495  for (size_t k = 0; k < m_nsp; k++) {
496  m_diff[k+j*m_nsp] = m_wt[k] * rho / (wtm*wtm);
497  }
498 
499  m_tcon[j] = m_trans->thermalConductivity();
500  if (m_do_soret) {
501  m_trans->getThermalDiffCoeffs(m_dthermal.ptrColumn(0) + j*m_nsp);
502  }
503  }
504  } else { // mixture averaged transport
505  for (size_t j = j0; j < j1; j++) {
506  setGasAtMidpoint(x,j);
507  m_visc[j] = (m_dovisc ? m_trans->viscosity() : 0.0);
508  m_trans->getMixDiffCoeffs(&m_diff[j*m_nsp]);
509  m_tcon[j] = m_trans->thermalConductivity();
510  }
511  }
512 }
513 
514 void StFlow::showSolution(const doublereal* x)
515 {
516  writelog(" Pressure: {:10.4g} Pa\n", m_press);
517 
519 
520  if (m_do_radiation) {
521  writeline('-', 79, false, true);
522  writelog("\n z radiative heat loss");
523  writeline('-', 79, false, true);
524  for (size_t j = 0; j < m_points; j++) {
525  writelog("\n {:10.4g} {:10.4g}", m_z[j], m_qdotRadiation[j]);
526  }
527  writelog("\n");
528  }
529 }
530 
531 void StFlow::updateDiffFluxes(const doublereal* x, size_t j0, size_t j1)
532 {
533  if (m_do_multicomponent) {
534  for (size_t j = j0; j < j1; j++) {
535  double dz = z(j+1) - z(j);
536  for (size_t k = 0; k < m_nsp; k++) {
537  doublereal sum = 0.0;
538  for (size_t m = 0; m < m_nsp; m++) {
539  sum += m_wt[m] * m_multidiff[mindex(k,m,j)] * (X(x,m,j+1)-X(x,m,j));
540  }
541  m_flux(k,j) = sum * m_diff[k+j*m_nsp] / dz;
542  }
543  }
544  } else {
545  for (size_t j = j0; j < j1; j++) {
546  double sum = 0.0;
547  double wtm = m_wtm[j];
548  double rho = density(j);
549  double dz = z(j+1) - z(j);
550  for (size_t k = 0; k < m_nsp; k++) {
551  m_flux(k,j) = m_wt[k]*(rho*m_diff[k+m_nsp*j]/wtm);
552  m_flux(k,j) *= (X(x,k,j) - X(x,k,j+1))/dz;
553  sum -= m_flux(k,j);
554  }
555  // correction flux to insure that \sum_k Y_k V_k = 0.
556  for (size_t k = 0; k < m_nsp; k++) {
557  m_flux(k,j) += sum*Y(x,k,j);
558  }
559  }
560  }
561 
562  if (m_do_soret) {
563  for (size_t m = j0; m < j1; m++) {
564  double gradlogT = 2.0 * (T(x,m+1) - T(x,m)) /
565  ((T(x,m+1) + T(x,m)) * (z(m+1) - z(m)));
566  for (size_t k = 0; k < m_nsp; k++) {
567  m_flux(k,m) -= m_dthermal(k,m)*gradlogT;
568  }
569  }
570  }
571 }
572 
573 string StFlow::componentName(size_t n) const
574 {
575  switch (n) {
576  case 0:
577  return "velocity";
578  case 1:
579  return "spread_rate";
580  case 2:
581  return "T";
582  case 3:
583  return "lambda";
584  case 4:
585  return "eField";
586  default:
587  if (n >= c_offset_Y && n < (c_offset_Y + m_nsp)) {
588  return m_thermo->speciesName(n - c_offset_Y);
589  } else {
590  return "<unknown>";
591  }
592  }
593 }
594 
595 size_t StFlow::componentIndex(const std::string& name) const
596 {
597  if (name=="u") {
598  warn_deprecated("StFlow::componentIndex",
599  "To be changed after Cantera 2.5. "
600  "Solution component 'u' renamed to 'velocity'");
601  return 0;
602  } else if (name=="velocity") {
603  return 0;
604  } else if (name=="V") {
605  warn_deprecated("StFlow::componentIndex",
606  "To be changed after Cantera 2.5. "
607  "Solution component 'V' renamed to 'spread_rate'");
608  return 1;
609  } else if (name=="spread_rate") {
610  return 1;
611  } else if (name=="T") {
612  return 2;
613  } else if (name=="lambda") {
614  return 3;
615  } else if (name == "eField") {
616  return 4;
617  } else {
618  for (size_t n=c_offset_Y; n<m_nsp+c_offset_Y; n++) {
619  if (componentName(n)==name) {
620  return n;
621  }
622  }
623  throw CanteraError("StFlow1D::componentIndex",
624  "no component named " + name);
625  }
626 }
627 
628 void StFlow::restore(const XML_Node& dom, doublereal* soln, int loglevel)
629 {
630  Domain1D::restore(dom, soln, loglevel);
631  vector<string> ignored;
632  size_t nsp = m_thermo->nSpecies();
633  vector_int did_species(nsp, 0);
634 
635  vector<XML_Node*> str = dom.getChildren("string");
636  for (size_t istr = 0; istr < str.size(); istr++) {
637  const XML_Node& nd = *str[istr];
638  writelog(nd["title"]+": "+nd.value()+"\n");
639  }
640 
641  double pp = getFloat(dom, "pressure", "pressure");
642  setPressure(pp);
643  vector<XML_Node*> d = dom.child("grid_data").getChildren("floatArray");
644  vector_fp x;
645  size_t np = 0;
646  bool readgrid = false, wrote_header = false;
647  for (size_t n = 0; n < d.size(); n++) {
648  const XML_Node& fa = *d[n];
649  string nm = fa["title"];
650  if (nm == "z") {
651  getFloatArray(fa,x,false);
652  np = x.size();
653  if (loglevel >= 2) {
654  writelog("Grid contains {} points.\n", np);
655  }
656  readgrid = true;
657  setupGrid(np, x.data());
658  }
659  }
660  if (!readgrid) {
661  throw CanteraError("StFlow::restore",
662  "domain contains no grid points.");
663  }
664 
665  debuglog("Importing datasets:\n", loglevel >= 2);
666  for (size_t n = 0; n < d.size(); n++) {
667  const XML_Node& fa = *d[n];
668  string nm = fa["title"];
669  getFloatArray(fa,x,false);
670  if (nm == "u") {
671  debuglog("axial velocity ", loglevel >= 2);
672  if (x.size() != np) {
673  throw CanteraError("StFlow::restore",
674  "axial velocity array size error");
675  }
676  for (size_t j = 0; j < np; j++) {
677  soln[index(c_offset_U,j)] = x[j];
678  }
679  } else if (nm == "z") {
680  ; // already read grid
681  } else if (nm == "V") {
682  debuglog("radial velocity ", loglevel >= 2);
683  if (x.size() != np) {
684  throw CanteraError("StFlow::restore",
685  "radial velocity array size error");
686  }
687  for (size_t j = 0; j < np; j++) {
688  soln[index(c_offset_V,j)] = x[j];
689  }
690  } else if (nm == "T") {
691  debuglog("temperature ", loglevel >= 2);
692  if (x.size() != np) {
693  throw CanteraError("StFlow::restore",
694  "temperature array size error");
695  }
696  for (size_t j = 0; j < np; j++) {
697  soln[index(c_offset_T,j)] = x[j];
698  }
699 
700  // For fixed-temperature simulations, use the imported temperature
701  // profile by default. If this is not desired, call
702  // setFixedTempProfile *after* restoring the solution.
703  vector_fp zz(np);
704  for (size_t jj = 0; jj < np; jj++) {
705  zz[jj] = (grid(jj) - zmin())/(zmax() - zmin());
706  }
707  setFixedTempProfile(zz, x);
708  } else if (nm == "L") {
709  debuglog("lambda ", loglevel >= 2);
710  if (x.size() != np) {
711  throw CanteraError("StFlow::restore",
712  "lambda arary size error");
713  }
714  for (size_t j = 0; j < np; j++) {
715  soln[index(c_offset_L,j)] = x[j];
716  }
717  } else if (m_thermo->speciesIndex(nm) != npos) {
718  debuglog(nm+" ", loglevel >= 2);
719  if (x.size() == np) {
720  size_t k = m_thermo->speciesIndex(nm);
721  did_species[k] = 1;
722  for (size_t j = 0; j < np; j++) {
723  soln[index(k+c_offset_Y,j)] = x[j];
724  }
725  }
726  } else {
727  ignored.push_back(nm);
728  }
729  }
730 
731  if (loglevel >=2 && !ignored.empty()) {
732  writelog("\n\n");
733  writelog("Ignoring datasets:\n");
734  size_t nn = ignored.size();
735  for (size_t n = 0; n < nn; n++) {
736  writelog(ignored[n]+" ");
737  }
738  }
739 
740  if (loglevel >= 1) {
741  for (size_t ks = 0; ks < nsp; ks++) {
742  if (did_species[ks] == 0) {
743  if (!wrote_header) {
744  writelog("Missing data for species:\n");
745  wrote_header = true;
746  }
747  writelog(m_thermo->speciesName(ks)+" ");
748  }
749  }
750  }
751 
752  if (dom.hasChild("energy_enabled")) {
753  getFloatArray(dom, x, false, "", "energy_enabled");
754  if (x.size() == nPoints()) {
755  for (size_t i = 0; i < x.size(); i++) {
756  m_do_energy[i] = (x[i] != 0);
757  }
758  } else if (!x.empty()) {
759  throw CanteraError("StFlow::restore", "energy_enabled is length {}"
760  "but should be length {}", x.size(), nPoints());
761  }
762  }
763 
764  if (dom.hasChild("species_enabled")) {
765  getFloatArray(dom, x, false, "", "species_enabled");
766  if (x.size() == m_nsp) {
767  for (size_t i = 0; i < x.size(); i++) {
768  m_do_species[i] = (x[i] != 0);
769  }
770  } else if (!x.empty()) {
771  // This may occur when restoring from a mechanism with a different
772  // number of species.
773  if (loglevel > 0) {
774  warn_user("StFlow::restore", "species_enabled is "
775  "length {} but should be length {}. Enabling all species "
776  "equations by default.", x.size(), m_nsp);
777  }
778  m_do_species.assign(m_nsp, true);
779  }
780  }
781 
782  if (dom.hasChild("refine_criteria")) {
783  XML_Node& ref = dom.child("refine_criteria");
784  refiner().setCriteria(getFloat(ref, "ratio"), getFloat(ref, "slope"),
785  getFloat(ref, "curve"), getFloat(ref, "prune"));
786  refiner().setGridMin(getFloat(ref, "grid_min"));
787  }
788 
789  if (domainType() == cFreeFlow) {
790  getOptionalFloat(dom, "t_fixed", m_tfixed);
791  getOptionalFloat(dom, "z_fixed", m_zfixed);
792  }
793 }
794 
795 XML_Node& StFlow::save(XML_Node& o, const doublereal* const sol)
796 {
797  Array2D soln(m_nv, m_points, sol + loc());
798  XML_Node& flow = Domain1D::save(o, sol);
799  flow.addAttribute("type",flowType());
800 
801  if (m_desc != "") {
802  addString(flow,"description",m_desc);
803  }
804  XML_Node& gv = flow.addChild("grid_data");
805  addFloat(flow, "pressure", m_press, "Pa", "pressure");
806 
807  addFloatArray(gv,"z",m_z.size(), m_z.data(),
808  "m","length");
809  vector_fp x(soln.nColumns());
810 
811  soln.getRow(c_offset_U, x.data());
812  addFloatArray(gv,"u",x.size(),x.data(),"m/s","velocity");
813 
814  soln.getRow(c_offset_V, x.data());
815  addFloatArray(gv,"V",x.size(),x.data(),"1/s","rate");
816 
817  soln.getRow(c_offset_T, x.data());
818  addFloatArray(gv,"T",x.size(),x.data(),"K","temperature");
819 
820  soln.getRow(c_offset_L, x.data());
821  addFloatArray(gv,"L",x.size(),x.data(),"N/m^4");
822 
823  for (size_t k = 0; k < m_nsp; k++) {
824  soln.getRow(c_offset_Y+k, x.data());
825  addFloatArray(gv,m_thermo->speciesName(k),
826  x.size(),x.data(),"","massFraction");
827  }
828  if (m_do_radiation) {
829  addFloatArray(gv, "radiative_heat_loss", m_z.size(),
830  m_qdotRadiation.data(), "W/m^3", "specificPower");
831  }
832  vector_fp values(nPoints());
833  for (size_t i = 0; i < nPoints(); i++) {
834  values[i] = m_do_energy[i];
835  }
836  addNamedFloatArray(flow, "energy_enabled", nPoints(), &values[0]);
837 
838  values.resize(m_nsp);
839  for (size_t i = 0; i < m_nsp; i++) {
840  values[i] = m_do_species[i];
841  }
842  addNamedFloatArray(flow, "species_enabled", m_nsp, &values[0]);
843 
844  XML_Node& ref = flow.addChild("refine_criteria");
845  addFloat(ref, "ratio", refiner().maxRatio());
846  addFloat(ref, "slope", refiner().maxDelta());
847  addFloat(ref, "curve", refiner().maxSlope());
848  addFloat(ref, "prune", refiner().prune());
849  addFloat(ref, "grid_min", refiner().gridMin());
850  if (m_zfixed != Undef) {
851  addFloat(flow, "z_fixed", m_zfixed, "m");
852  addFloat(flow, "t_fixed", m_tfixed, "K");
853  }
854  return flow;
855 }
856 
857 void StFlow::solveEnergyEqn(size_t j)
858 {
859  bool changed = false;
860  if (j == npos) {
861  for (size_t i = 0; i < m_points; i++) {
862  if (!m_do_energy[i]) {
863  changed = true;
864  }
865  m_do_energy[i] = true;
866  }
867  } else {
868  if (!m_do_energy[j]) {
869  changed = true;
870  }
871  m_do_energy[j] = true;
872  }
873  m_refiner->setActive(c_offset_U, true);
874  m_refiner->setActive(c_offset_V, true);
875  m_refiner->setActive(c_offset_T, true);
876  if (changed) {
877  needJacUpdate();
878  }
879 }
880 
881 void StFlow::setBoundaryEmissivities(doublereal e_left, doublereal e_right)
882 {
883  if (e_left < 0 || e_left > 1) {
884  throw CanteraError("StFlow::setBoundaryEmissivities",
885  "The left boundary emissivity must be between 0.0 and 1.0!");
886  } else if (e_right < 0 || e_right > 1) {
887  throw CanteraError("StFlow::setBoundaryEmissivities",
888  "The right boundary emissivity must be between 0.0 and 1.0!");
889  } else {
890  m_epsilon_left = e_left;
891  m_epsilon_right = e_right;
892  }
893 }
894 
895 void StFlow::fixTemperature(size_t j)
896 {
897  bool changed = false;
898  if (j == npos) {
899  for (size_t i = 0; i < m_points; i++) {
900  if (m_do_energy[i]) {
901  changed = true;
902  }
903  m_do_energy[i] = false;
904  }
905  } else {
906  if (m_do_energy[j]) {
907  changed = true;
908  }
909  m_do_energy[j] = false;
910  }
911  m_refiner->setActive(c_offset_U, false);
912  m_refiner->setActive(c_offset_V, false);
913  m_refiner->setActive(c_offset_T, false);
914  if (changed) {
915  needJacUpdate();
916  }
917 }
918 
919 void StFlow::evalRightBoundary(double* x, double* rsd, int* diag, double rdt)
920 {
921  size_t j = m_points - 1;
922 
923  // the boundary object connected to the right of this one may modify or
924  // replace these equations. The default boundary conditions are zero u, V,
925  // and T, and zero diffusive flux for all species.
926 
927  rsd[index(c_offset_V,j)] = V(x,j);
928  doublereal sum = 0.0;
929  rsd[index(c_offset_L, j)] = lambda(x,j) - lambda(x,j-1);
930  diag[index(c_offset_L, j)] = 0;
931  for (size_t k = 0; k < m_nsp; k++) {
932  sum += Y(x,k,j);
933  rsd[index(k+c_offset_Y,j)] = m_flux(k,j-1) + rho_u(x,j)*Y(x,k,j);
934  }
935  rsd[index(c_offset_Y + rightExcessSpecies(), j)] = 1.0 - sum;
936  diag[index(c_offset_Y + rightExcessSpecies(), j)] = 0;
937  if (domainType() == cAxisymmetricStagnationFlow) {
938  rsd[index(c_offset_U,j)] = rho_u(x,j);
939  if (m_do_energy[j]) {
940  rsd[index(c_offset_T,j)] = T(x,j);
941  } else {
942  rsd[index(c_offset_T, j)] = T(x,j) - T_fixed(j);
943  }
944  } else if (domainType() == cFreeFlow) {
945  rsd[index(c_offset_U,j)] = rho_u(x,j) - rho_u(x,j-1);
946  rsd[index(c_offset_T,j)] = T(x,j) - T(x,j-1);
947  }
948 }
949 
950 void StFlow::evalContinuity(size_t j, double* x, double* rsd, int* diag, double rdt)
951 {
952  //algebraic constraint
953  diag[index(c_offset_U, j)] = 0;
954  //----------------------------------------------
955  // Continuity equation
956  //
957  // d(\rho u)/dz + 2\rho V = 0
958  //----------------------------------------------
959  if (domainType() == cAxisymmetricStagnationFlow) {
960  // Note that this propagates the mass flow rate information to the left
961  // (j+1 -> j) from the value specified at the right boundary. The
962  // lambda information propagates in the opposite direction.
963  rsd[index(c_offset_U,j)] =
964  -(rho_u(x,j+1) - rho_u(x,j))/m_dz[j]
965  -(density(j+1)*V(x,j+1) + density(j)*V(x,j));
966  } else if (domainType() == cFreeFlow) {
967  if (grid(j) > m_zfixed) {
968  rsd[index(c_offset_U,j)] =
969  - (rho_u(x,j) - rho_u(x,j-1))/m_dz[j-1]
970  - (density(j-1)*V(x,j-1) + density(j)*V(x,j));
971  } else if (grid(j) == m_zfixed) {
972  if (m_do_energy[j]) {
973  rsd[index(c_offset_U,j)] = (T(x,j) - m_tfixed);
974  } else {
975  rsd[index(c_offset_U,j)] = (rho_u(x,j)
976  - m_rho[0]*0.3);
977  }
978  } else if (grid(j) < m_zfixed) {
979  rsd[index(c_offset_U,j)] =
980  - (rho_u(x,j+1) - rho_u(x,j))/m_dz[j]
981  - (density(j+1)*V(x,j+1) + density(j)*V(x,j));
982  }
983  }
984 }
985 
986 } // namespace
Headers for the Transport object, which is the virtual base class for all transport property evaluato...
A class for 2D arrays stored in column-major (Fortran-compatible) form.
Definition: Array.h:32
void resize(size_t n, size_t m, doublereal v=0.0)
Resize the array, and fill the new entries with 'v'.
Definition: Array.h:112
doublereal * ptrColumn(size_t j)
Return a pointer to the top of column j, columns are contiguous in memory.
Definition: Array.h:292
size_t nColumns() const
Number of columns.
Definition: Array.h:252
void getRow(size_t n, doublereal *const rw)
Get the nth row and return it in a vector.
Definition: Array.h:165
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:61
Base class for one-dimensional domains.
Definition: Domain1D.h:39
size_t lastPoint() const
The index of the last (i.e., right-most) grid point belonging to this domain.
Definition: Domain1D.h:375
virtual void showSolution(const doublereal *x)
Print the solution.
Definition: Domain1D.cpp:194
size_t nPoints() const
Number of grid points in this domain.
Definition: Domain1D.h:156
virtual XML_Node & save(XML_Node &o, const doublereal *const sol)
Save the current solution for this domain into an XML_Node.
Definition: Domain1D.cpp:110
virtual void resize(size_t nv, size_t np)
Definition: Domain1D.cpp:33
virtual void restore(const XML_Node &dom, doublereal *soln, int loglevel)
Restore the solution for this domain from an XML_Node.
Definition: Domain1D.cpp:123
Refiner & refiner()
Return a reference to the grid refiner.
Definition: Domain1D.h:129
int domainType()
Domain type flag.
Definition: Domain1D.h:54
size_t firstPoint() const
The index of the first (i.e., left-most) grid point belonging to this domain.
Definition: Domain1D.h:367
void needJacUpdate()
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:359
Class IdealGasPhase represents low-density gases that obey the ideal gas equation of state.
const vector_fp & enthalpy_RT_ref() const
Returns a reference to the dimensionless reference state enthalpy vector.
const vector_fp & cp_R_ref() const
Returns a reference to the dimensionless reference state Heat Capacity vector.
virtual void setPressure(doublereal p)
Set the pressure at constant temperature and composition.
size_t nSpecies() const
Returns the number of species in the phase.
Definition: Phase.h:285
virtual void setMassFractions_NoNorm(const double *const y)
Set the mass fractions to the specified values without normalizing.
Definition: Phase.cpp:434
const vector_fp & molecularWeights() const
Return a const reference to the internal vector of molecular weights.
Definition: Phase.cpp:538
std::string speciesName(size_t k) const
Name of the species with index k.
Definition: Phase.cpp:229
doublereal meanMolecularWeight() const
The mean molecular weight. Units: (kg/kmol)
Definition: Phase.h:748
virtual double density() const
Density (kg/m^3).
Definition: Phase.h:685
doublereal temperature() const
Temperature (K).
Definition: Phase.h:667
virtual void setMassFractions(const double *const y)
Set the mass fractions to the specified values and normalize them.
Definition: Phase.cpp:420
size_t speciesIndex(const std::string &name) const
Returns the index of a species named 'name' within the Phase object.
Definition: Phase.cpp:201
virtual void setTemperature(const doublereal temp)
Set the internally stored temperature of the phase (K).
Definition: Phase.h:724
void getMassFractions(double *const y) const
Get the species mass fractions.
Definition: Phase.cpp:614
void setCriteria(doublereal ratio=10.0, doublereal slope=0.8, doublereal curve=0.8, doublereal prune=-0.1)
Set grid refinement criteria.
Definition: refine.cpp:23
void setGridMin(double gridmin)
Set the minimum allowable spacing between adjacent grid points [m].
Definition: refine.h:62
virtual void evalResidual(double *x, double *rsd, int *diag, double rdt, size_t jmin, size_t jmax)
Evaluate the residual function.
Definition: StFlow.cpp:290
virtual void evalRightBoundary(double *x, double *res, int *diag, double rdt)
Evaluate all residual components at the right boundary.
Definition: StFlow.cpp:919
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:950
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:475
virtual void showSolution(const doublereal *x)
Print the solution.
Definition: StFlow.cpp:514
void setGasAtMidpoint(const doublereal *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:179
size_t rightExcessSpecies() const
Index of the species on the right boundary with the largest mass fraction.
Definition: StFlow.h:284
doublereal T_fixed(size_t j) const
The fixed temperature value at point j.
Definition: StFlow.h:130
void setBoundaryEmissivities(double e_left, double e_right)
Set the emissivities for the boundary values.
Definition: StFlow.cpp:881
std::vector< size_t > m_kRadiating
Indices within the ThermoPhase of the radiating species.
Definition: StFlow.h:453
virtual void eval(size_t j, doublereal *x, doublereal *r, integer *mask, doublereal rdt)
Definition: StFlow.cpp:238
virtual XML_Node & save(XML_Node &o, const doublereal *const sol)
Save the current solution for this domain into an XML_Node.
Definition: StFlow.cpp:795
double m_tfixed
Temperature at the point used to fix the flame location.
Definition: StFlow.h:489
void setPressure(doublereal p)
Set the pressure.
Definition: StFlow.h:98
virtual void restore(const XML_Node &dom, doublereal *soln, int loglevel)
Restore the solution for this domain from an XML_Node.
Definition: StFlow.cpp:628
void getWdot(doublereal *x, size_t j)
Write the net production rates at point j into array m_wdot
Definition: StFlow.h:294
virtual void _finalize(const doublereal *x)
In some cases, a domain may need to set parameters that depend on the initial solution estimate.
Definition: StFlow.cpp:191
virtual std::string componentName(size_t n) const
Name of the nth component. May be overloaded.
Definition: StFlow.cpp:573
void setGas(const doublereal *x, size_t j)
Set the gas object state to be consistent with the solution at point j.
Definition: StFlow.cpp:171
virtual void updateDiffFluxes(const doublereal *x, size_t j0, size_t j1)
Update the diffusive mass fluxes.
Definition: StFlow.cpp:531
void setFixedTempProfile(vector_fp &zfixed, vector_fp &tfixed)
Sometimes it is desired to carry out the simulation using a specified temperature profile,...
Definition: StFlow.h:115
virtual void resize(size_t components, size_t points)
Change the grid size. Called after grid refinement.
Definition: StFlow.cpp:102
size_t leftExcessSpecies() const
Index of the species on the left boundary with the largest mass fraction.
Definition: StFlow.h:279
double m_zfixed
Location of the point where temperature is fixed.
Definition: StFlow.h:486
void updateThermo(const doublereal *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:313
virtual void updateTransport(doublereal *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:484
vector_fp m_qdotRadiation
radiative heat loss vector
Definition: StFlow.h:465
virtual void resetBadValues(double *xg)
Definition: StFlow.cpp:141
virtual void _getInitialSoln(double *x)
Write the initial solution estimate into array x.
Definition: StFlow.cpp:163
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:266
virtual std::string flowType()
Return the type of flow domain being represented, either "Free Flame" or "Axisymmetric Stagnation".
Definition: StFlow.h:176
virtual void setupGrid(size_t n, const doublereal *z)
called to set up initial grid, and after grid refinement
Definition: StFlow.cpp:126
void setTransport(Transport &trans)
set the transport manager
Definition: StFlow.cpp:151
virtual size_t componentIndex(const std::string &name) const
index of component with name name.
Definition: StFlow.cpp:595
bool m_do_radiation
flag for the radiative heat loss
Definition: StFlow.h:462
Base class for a phase with thermodynamic properties.
Definition: ThermoPhase.h:102
virtual doublereal maxTemp(size_t k=npos) const
Maximum temperature for which the thermodynamic data for the species are valid.
Definition: ThermoPhase.h:213
virtual std::string type() const
String indicating the thermodynamic model implemented.
Definition: ThermoPhase.h:113
Base class for transport property managers.
virtual void getThermalDiffCoeffs(doublereal *const dt)
Return a vector of Thermal diffusion coefficients [kg/m/sec].
virtual doublereal viscosity()
virtual std::string transportType() const
Identifies the Transport object type.
virtual void getMultiDiffCoeffs(const size_t ld, doublereal *const d)
Return the Multicomponent diffusion coefficients. Units: [m^2/s].
virtual doublereal thermalConductivity()
Returns the mixture thermal conductivity in W/m/K.
virtual void getMixDiffCoeffs(doublereal *const d)
Returns a vector of mixture averaged diffusion coefficients.
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:104
bool hasChild(const std::string &ch) const
Tests whether the current node has a child node with a particular name.
Definition: xml.cpp:528
void addAttribute(const std::string &attrib, const std::string &value)
Add or modify an attribute of the current node.
Definition: xml.cpp:466
std::vector< XML_Node * > getChildren(const std::string &name) const
Get a vector of pointers to XML_Node containing all of the children of the current node which match t...
Definition: xml.cpp:711
std::string value() const
Return the value of an XML node as a string.
Definition: xml.cpp:441
XML_Node & child(const size_t n) const
Return a changeable reference to the n'th child of the current node.
Definition: xml.cpp:546
CTML ("Cantera Markup Language") is the variant of XML that Cantera uses to store data.
Header for a file containing miscellaneous numerical functions.
void debuglog(const std::string &msg, int loglevel)
Write a message to the log only if loglevel > 0.
Definition: global.h:140
void warn_user(const std::string &method, const std::string &msg, const Args &... args)
Definition: global.h:206
void warn_deprecated(const std::string &method, const std::string &extra)
Print a warning indicating that method is deprecated.
Definition: global.cpp:54
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:188
const double Undef
Fairly random number to be used to initialize variables against to see if they are subsequently defin...
Definition: ct_defs.h:157
const double OneAtm
One atmosphere [Pa].
Definition: ct_defs.h:78
std::vector< int > vector_int
Vector of ints.
Definition: ct_defs.h:182
const double StefanBoltz
Stefan-Boltzmann constant [W/m2/K4].
Definition: ct_defs.h:120
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
Definition: ct_defs.h:180
const double GasConstant
Universal Gas Constant [J/kmol/K].
Definition: ct_defs.h:109
void writelog(const std::string &fmt, const Args &... args)
Write a formatted message to the screen.
Definition: global.h:158
Namespace for the Cantera kernel.
Definition: AnyMap.cpp:264
doublereal linearInterp(doublereal x, const vector_fp &xpts, const vector_fp &fpts)
Linearly interpolate a function defined on a discrete grid.
Definition: funcs.cpp:13
doublereal getFloat(const XML_Node &parent, const std::string &name, const std::string &type)
Get a floating-point value from a child element.
Definition: ctml.cpp:164
bool getOptionalFloat(const XML_Node &parent, const std::string &name, doublereal &fltRtn, const std::string &type)
Get an optional floating-point value from a child element.
Definition: ctml.cpp:212
void addFloat(XML_Node &node, const std::string &title, const doublereal val, const std::string &units, const std::string &type, const doublereal minval, const doublereal maxval)
This function adds a child node with the name, "float", with a value consisting of a single floating ...
Definition: ctml.cpp:19
size_t getFloatArray(const XML_Node &node, vector_fp &v, const bool convert, const std::string &unitsString, const std::string &nodeName)
This function reads the current node or a child node of the current node with the default name,...
Definition: ctml.cpp:256
void addString(XML_Node &node, const std::string &titleString, const std::string &valueString, const std::string &typeString)
This function adds a child node with the name string with a string value to the current node.
Definition: ctml.cpp:111
void addFloatArray(XML_Node &node, const std::string &title, const size_t n, const doublereal *const vals, const std::string &units, const std::string &type, const doublereal minval, const doublereal maxval)
This function adds a child node with the name, "floatArray", with a value consisting of a comma separ...
Definition: ctml.cpp:40
void addNamedFloatArray(XML_Node &node, const std::string &name, const size_t n, const doublereal *const vals, const std::string units, const std::string type, const doublereal minval, const doublereal maxval)
This function adds a child node with the name given by the first parameter with a value consisting of...
Definition: ctml.cpp:73