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