Cantera  2.0
StFlow.h
Go to the documentation of this file.
1 /**
2  * @file StFlow.h
3  *
4  */
5 // Copyright 2001 California Institute of Technology
6 
7 #ifndef CT_STFLOW_H
8 #define CT_STFLOW_H
9 
11 #include "Domain1D.h"
12 #include "cantera/base/Array.h"
15 #include "cantera/numerics/funcs.h"
16 //#include "../flowBoundaries.h"
17 
18 
19 namespace Cantera
20 {
21 class MultiJac;
22 
23 //------------------------------------------
24 // constants
25 //------------------------------------------
26 
27 // Offsets of solution components in the solution array.
28 const size_t c_offset_U = 0; // axial velocity
29 const size_t c_offset_V = 1; // strain rate
30 const size_t c_offset_T = 2; // temperature
31 const size_t c_offset_L = 3; // (1/r)dP/dr
32 const size_t c_offset_Y = 4; // mass fractions
33 
34 // Transport option flags
35 const int c_Mixav_Transport = 0;
36 const int c_Multi_Transport = 1;
37 const int c_Soret = 2;
38 
39 //-----------------------------------------------------------
40 // Class StFlow
41 //-----------------------------------------------------------
42 
43 
44 /**
45  * This class represents 1D flow domains that satisfy the
46  * one-dimensional similarity solution for chemically-reacting,
47  * axisymmetric, flows.
48  */
49 class StFlow : public Domain1D
50 {
51 
52 public:
53 
54  //--------------------------------
55  // construction and destruction
56  //--------------------------------
57 
58  /// Constructor. Create a new flow domain.
59  /// @param ph Object representing the gas phase. This object
60  /// will be used to evaluate all thermodynamic, kinetic, and transport
61  /// properties.
62  /// @param nsp Number of species.
63  StFlow(IdealGasPhase* ph = 0, size_t nsp = 1, size_t points = 1);
64 
65  /// Destructor.
66  virtual ~StFlow() {}
67 
68  /**
69  * @name Problem Specification
70  */
71  //@{
72 
73  virtual void setupGrid(size_t n, const doublereal* z);
74 
75  thermo_t& phase() {
76  return *m_thermo;
77  }
78  Kinetics& kinetics() {
79  return *m_kin;
80  }
81 
82  virtual void init() {
83  }
84 
85  /**
86  * Set the thermo manager. Note that the flow equations assume
87  * the ideal gas equation.
88  */
90  m_thermo = &th;
91  }
92 
93  /// Set the kinetics manager. The kinetics manager must
94  void setKinetics(Kinetics& kin) {
95  m_kin = &kin;
96  }
97 
98  /// set the transport manager
99  void setTransport(Transport& trans, bool withSoret = false);
100  void enableSoret(bool withSoret);
101  bool withSoret() const {
102  return m_do_soret;
103  }
104 
105  /// Set the pressure. Since the flow equations are for the limit of
106  /// small Mach number, the pressure is very nearly constant
107  /// throughout the flow.
108  void setPressure(doublereal p) {
109  m_press = p;
110  }
111 
112 
113  /// @todo remove? may be unused
114  virtual void setState(size_t point, const doublereal* state,
115  doublereal* x) {
116  setTemperature(point, state[2]);
117  for (size_t k = 0; k < m_nsp; k++) {
118  setMassFraction(point, k, state[4+k]);
119  }
120  }
121 
122 
123  /// Write the initial solution estimate into
124  /// array x.
125  virtual void _getInitialSoln(doublereal* x) {
126  for (size_t j = 0; j < m_points; j++) {
127  x[index(2,j)] = T_fixed(j);
128  for (size_t k = 0; k < m_nsp; k++) {
129  x[index(4+k,j)] = Y_fixed(k,j);
130  }
131  }
132  }
133 
134  virtual void _finalize(const doublereal* x);
135 
136 
137  /// Sometimes it is desired to carry out the simulation
138  /// using a specified temperature profile, rather than
139  /// computing it by solving the energy equation. This
140  /// method specifies this profile.
141  void setFixedTempProfile(vector_fp& zfixed, vector_fp& tfixed) {
142  m_zfix = zfixed;
143  m_tfix = tfixed;
144  }
145 
146  /**
147  * Set the temperature fixed point at grid point j, and
148  * disable the energy equation so that the solution will be
149  * held to this value.
150  */
151  void setTemperature(size_t j, doublereal t) {
152  m_fixedtemp[j] = t;
153  m_do_energy[j] = false;
154  }
155 
156  /**
157  * Set the mass fraction fixed point for species k at grid
158  * point j, and disable the species equation so that the
159  * solution will be held to this value.
160  * note: in practice, the species are hardly ever held fixed.
161  */
162  void setMassFraction(size_t j, size_t k, doublereal y) {
163  m_fixedy(k,j) = y;
164  m_do_species[k] = true; // false;
165  }
166 
167 
168  /// The fixed temperature value at point j.
169  doublereal T_fixed(size_t j) const {
170  return m_fixedtemp[j];
171  }
172 
173 
174  /// The fixed mass fraction value of species k at point j.
175  doublereal Y_fixed(size_t k, size_t j) const {
176  return m_fixedy(k,j);
177  }
178 
179 
180  virtual std::string componentName(size_t n) const;
181 
182  size_t componentIndex(std::string name) const;
183 
184 
185  virtual void showSolution(const doublereal* x);
186 
187  //! Save the current solution for this domain into an XML_Node
188  /*!
189  *
190  * @param o XML_Node to save the solution to.
191  * @param sol Current value of the solution vector.
192  * The object will pick out which part of the solution
193  * vector pertains to this object.
194  */
195  virtual void save(XML_Node& o, const doublereal* const sol);
196 
197  virtual void restore(const XML_Node& dom, doublereal* soln);
198 
199  // overloaded in subclasses
200  virtual std::string flowType() {
201  return "<none>";
202  }
203 
204  void solveEnergyEqn(size_t j=npos) {
205  if (j == npos)
206  for (size_t i = 0; i < m_points; i++) {
207  m_do_energy[i] = true;
208  }
209  else {
210  m_do_energy[j] = true;
211  }
212  m_refiner->setActive(0, true);
213  m_refiner->setActive(1, true);
214  m_refiner->setActive(2, true);
215  needJacUpdate();
216  }
217 
218  void fixTemperature(size_t j=npos) {
219  if (j == npos)
220  for (size_t i = 0; i < m_points; i++) {
221  m_do_energy[i] = false;
222  }
223  else {
224  m_do_energy[j] = false;
225  }
226  m_refiner->setActive(0, false);
227  m_refiner->setActive(1, false);
228  m_refiner->setActive(2, false);
229  needJacUpdate();
230  }
231 
232  bool doSpecies(size_t k) {
233  return m_do_species[k];
234  }
235  bool doEnergy(size_t j) {
236  return m_do_energy[j];
237  }
238 
239  void solveSpecies(size_t k=npos) {
240  if (k == npos) {
241  for (size_t i = 0; i < m_nsp; i++) {
242  m_do_species[i] = true;
243  }
244  } else {
245  m_do_species[k] = true;
246  }
247  needJacUpdate();
248  }
249 
250  void fixSpecies(size_t k=npos) {
251  if (k == npos) {
252  for (size_t i = 0; i < m_nsp; i++) {
253  m_do_species[i] = false;
254  }
255  } else {
256  m_do_species[k] = false;
257  }
258  needJacUpdate();
259  }
260 
261  void integrateChem(doublereal* x,doublereal dt);
262 
263  void resize(size_t components, size_t points);
264 
265  virtual void setFixedPoint(int j0, doublereal t0) {}
266 
267 
268  void setJac(MultiJac* jac);
269  void setGas(const doublereal* x, size_t j);
270  void setGasAtMidpoint(const doublereal* x, size_t j);
271 
272  doublereal density(size_t j) const {
273  return m_rho[j];
274  }
275 
276  virtual bool fixed_mdot() {
277  return true;
278  }
279  void setViscosityFlag(bool dovisc) {
280  m_dovisc = dovisc;
281  }
282 
283 protected:
284 
285  doublereal component(const doublereal* x, size_t i, size_t j) const {
286  doublereal xx = x[index(i,j)];
287  return xx;
288  }
289 
290  doublereal conc(const doublereal* x, size_t k,size_t j) const {
291  return Y(x,k,j)*density(j)/m_wt[k];
292  }
293 
294  doublereal cbar(const doublereal* x, size_t k, size_t j) const {
295  return std::sqrt(8.0*GasConstant * T(x,j) / (Pi * m_wt[k]));
296  }
297 
298  doublereal wdot(size_t k, size_t j) const {
299  return m_wdot(k,j);
300  }
301 
302  /// write the net production rates at point j into array m_wdot
303  void getWdot(doublereal* x, size_t j) {
304  setGas(x,j);
305  m_kin->getNetProductionRates(&m_wdot(0,j));
306  }
307 
308  /**
309  * update the thermodynamic properties from point
310  * j0 to point j1 (inclusive), based on solution x.
311  */
312  void updateThermo(const doublereal* x, size_t j0, size_t j1) {
313  for (size_t j = j0; j <= j1; j++) {
314  setGas(x,j);
315  m_rho[j] = m_thermo->density();
316  m_wtm[j] = m_thermo->meanMolecularWeight();
317  m_cp[j] = m_thermo->cp_mass();
318  }
319  }
320 
321 
322  //--------------------------------
323  // central-differenced derivatives
324  //--------------------------------
325 
326  doublereal cdif2(const doublereal* x, size_t n, size_t j,
327  const doublereal* f) const {
328  doublereal c1 = (f[j] + f[j-1])*(x[index(n,j)] - x[index(n,j-1)]);
329  doublereal c2 = (f[j+1] + f[j])*(x[index(n,j+1)] - x[index(n,j)]);
330  return (c2/(z(j+1) - z(j)) - c1/(z(j) - z(j-1)))/(z(j+1) - z(j-1));
331  }
332 
333 
334  //--------------------------------
335  // solution components
336  //--------------------------------
337 
338 
339  doublereal T(const doublereal* x, size_t j) const {
340  return x[index(c_offset_T, j)];
341  }
342  doublereal& T(doublereal* x, size_t j) {
343  return x[index(c_offset_T, j)];
344  }
345  doublereal T_prev(size_t j) const {
346  return prevSoln(c_offset_T, j);
347  }
348 
349  doublereal rho_u(const doublereal* x, size_t j) const {
350  return m_rho[j]*x[index(c_offset_U, j)];
351  }
352 
353  doublereal u(const doublereal* x, size_t j) const {
354  return x[index(c_offset_U, j)];
355  }
356 
357  doublereal V(const doublereal* x, size_t j) const {
358  return x[index(c_offset_V, j)];
359  }
360  doublereal V_prev(size_t j) const {
361  return prevSoln(c_offset_V, j);
362  }
363 
364  doublereal lambda(const doublereal* x, size_t j) const {
365  return x[index(c_offset_L, j)];
366  }
367 
368  doublereal Y(const doublereal* x, size_t k, size_t j) const {
369  return x[index(c_offset_Y + k, j)];
370  }
371 
372  doublereal& Y(doublereal* x, size_t k, size_t j) {
373  return x[index(c_offset_Y + k, j)];
374  }
375 
376  doublereal Y_prev(size_t k, size_t j) const {
377  return prevSoln(c_offset_Y + k, j);
378  }
379 
380  doublereal X(const doublereal* x, size_t k, size_t j) const {
381  return m_wtm[j]*Y(x,k,j)/m_wt[k];
382  }
383 
384  doublereal flux(size_t k, size_t j) const {
385  return m_flux(k, j);
386  }
387 
388 
389  // convective spatial derivatives. These use upwind
390  // differencing, assuming u(z) is negative
391 
392  doublereal dVdz(const doublereal* x, size_t j) const {
393  size_t jloc = (u(x,j) > 0.0 ? j : j + 1);
394  return (V(x,jloc) - V(x,jloc-1))/m_dz[jloc-1];
395  }
396 
397  doublereal dYdz(const doublereal* x, size_t k, size_t j) const {
398  size_t jloc = (u(x,j) > 0.0 ? j : j + 1);
399  return (Y(x,k,jloc) - Y(x,k,jloc-1))/m_dz[jloc-1];
400  }
401 
402  doublereal dTdz(const doublereal* x, size_t j) const {
403  size_t jloc = (u(x,j) > 0.0 ? j : j + 1);
404  return (T(x,jloc) - T(x,jloc-1))/m_dz[jloc-1];
405  }
406 
407  doublereal shear(const doublereal* x, size_t j) const {
408  doublereal c1 = m_visc[j-1]*(V(x,j) - V(x,j-1));
409  doublereal c2 = m_visc[j]*(V(x,j+1) - V(x,j));
410  return 2.0*(c2/(z(j+1) - z(j)) - c1/(z(j) - z(j-1)))/(z(j+1) - z(j-1));
411  }
412 
413  doublereal divHeatFlux(const doublereal* x, size_t j) const {
414  doublereal c1 = m_tcon[j-1]*(T(x,j) - T(x,j-1));
415  doublereal c2 = m_tcon[j]*(T(x,j+1) - T(x,j));
416  return -2.0*(c2/(z(j+1) - z(j)) - c1/(z(j) - z(j-1)))/(z(j+1) - z(j-1));
417  }
418 
419  size_t mindex(size_t k, size_t j, size_t m) {
420  return m*m_nsp*m_nsp + m_nsp*j + k;
421  }
422 
423  void updateDiffFluxes(const doublereal* x, size_t j0, size_t j1);
424 
425 
426  //---------------------------------------------------------
427  //
428  // member data
429  //
430  //---------------------------------------------------------
431 
432  // inlet
433  doublereal m_inlet_u;
434  doublereal m_inlet_V;
435  doublereal m_inlet_T;
436  doublereal m_rho_inlet;
437  vector_fp m_yin;
438 
439  // surface
440  doublereal m_surface_T;
441 
442  doublereal m_press; // pressure
443 
444  // grid parameters
445  vector_fp m_dz;
446  //vector_fp m_z;
447 
448  // mixture thermo properties
449  vector_fp m_rho;
450  vector_fp m_wtm;
451 
452  // species thermo properties
453  vector_fp m_wt;
454  vector_fp m_cp;
455  vector_fp m_enth;
456 
457  // transport properties
458  vector_fp m_visc;
459  vector_fp m_tcon;
460  vector_fp m_diff;
461  vector_fp m_multidiff;
462  Array2D m_dthermal;
463  Array2D m_flux;
464 
465  // production rates
466  Array2D m_wdot;
467  vector_fp m_surfdot;
468 
469  size_t m_nsp;
470 
471  IdealGasPhase* m_thermo;
472  Kinetics* m_kin;
473  Transport* m_trans;
474 
475  MultiJac* m_jac;
476 
477  bool m_ok;
478 
479  // flags
480  std::vector<bool> m_do_energy;
481  bool m_do_soret;
482  std::vector<bool> m_do_species;
483  int m_transport_option;
484 
485  // solution estimate
486  //vector_fp m_zest;
487  //Array2D m_yest;
488 
489  // fixed T and Y values
490  Array2D m_fixedy;
491  vector_fp m_fixedtemp;
492  vector_fp m_zfix;
493  vector_fp m_tfix;
494 
495  bool m_dovisc;
496  void updateTransport(doublereal* x, size_t j0, size_t j1);
497 
498 private:
499  vector_fp m_ybar;
500 
501 };
502 
503 
504 /**
505  * A class for axisymmetric stagnation flows.
506  */
507 class AxiStagnFlow : public StFlow
508 {
509 public:
510  AxiStagnFlow(IdealGasPhase* ph = 0, size_t nsp = 1, size_t points = 1) :
511  StFlow(ph, nsp, points) {
512  m_dovisc = true;
513  }
514  virtual ~AxiStagnFlow() {}
515  virtual void eval(size_t j, doublereal* x, doublereal* r,
516  integer* mask, doublereal rdt);
517  virtual std::string flowType() {
518  return "Axisymmetric Stagnation";
519  }
520 };
521 
522 /**
523  * A class for freely-propagating premixed flames.
524  */
525 class FreeFlame : public StFlow
526 {
527 public:
528  FreeFlame(IdealGasPhase* ph = 0, size_t nsp = 1, size_t points = 1) :
529  StFlow(ph, nsp, points) {
530  m_dovisc = false;
531  setID("flame");
532  }
533  virtual ~FreeFlame() {}
534  virtual void eval(size_t j, doublereal* x, doublereal* r,
535  integer* mask, doublereal rdt);
536  virtual std::string flowType() {
537  return "Free Flame";
538  }
539  virtual bool fixed_mdot() {
540  return false;
541  }
542 };
543 
544 
545 /*
546 class OneDFlow : public StFlow {
547 public:
548  OneDFlow(igthermo_t* ph = 0, int nsp = 1, int points = 1) :
549  StFlow(ph, nsp, points) {
550  }
551  virtual ~OneDFlow() {}
552  virtual void eval(int j, doublereal* x, doublereal* r,
553  integer* mask, doublereal rdt);
554  virtual std::string flowType() { return "OneDFlow"; }
555  doublereal mdot(doublereal* x, int j) {
556  return x[index(c_offset_L,j)];
557  }
558 
559 private:
560  void updateTransport(doublereal* x,int j0, int j1);
561 };
562 */
563 
564 void importSolution(size_t points, doublereal* oldSoln, IdealGasPhase& oldmech,
565  size_t size_new, doublereal* newSoln, IdealGasPhase& newmech);
566 
567 }
568 
569 #endif