Cantera  2.0
boundaries1D.cpp
Go to the documentation of this file.
1 /**
2  * @file boundaries1D.cpp
3  */
4 // Copyright 2002-3 California Institute of Technology
5 
6 #include "cantera/oneD/Inlet1D.h"
7 
8 using namespace std;
9 
10 namespace Cantera
11 {
12 
13 Bdry1D::Bdry1D() : Domain1D(1, 1, 0.0),
14  m_flow_left(0), m_flow_right(0),
15  m_ilr(0), m_left_nv(0), m_right_nv(0),
16  m_left_loc(0), m_right_loc(0),
17  m_left_points(0), m_nv(0),
18  m_left_nsp(0), m_right_nsp(0),
19  m_sp_left(0), m_sp_right(0),
20  m_start_left(0), m_start_right(0),
21  m_phase_left(0), m_phase_right(0), m_temp(0.0), m_mdot(0.0)
22 {
23  m_type = cConnectorType;
24 }
25 
26 
27 void Bdry1D::
28 _init(size_t n)
29 {
30  if (m_index == npos) {
31  throw CanteraError("Bdry1D",
32  "install in container before calling init.");
33  }
34 
35  // A boundary object contains only one grid point
36  resize(n,1);
37 
38  m_left_nsp = 0;
39  m_right_nsp = 0;
40 
41  // check for left and right flow objects
42  if (m_index > 0) {
43  Domain1D& r = container().domain(m_index-1);
44  if (r.domainType() == cFlowType) {
45  m_flow_left = (StFlow*)&r;
46  m_left_nv = m_flow_left->nComponents();
47  m_left_points = m_flow_left->nPoints();
48  m_left_loc = container().start(m_index-1);
49  m_left_nsp = m_left_nv - 4;
50  m_phase_left = &m_flow_left->phase();
51  } else
52  throw CanteraError("Bdry1D::init",
53  "Boundary domains can only be "
54  "connected on the left to flow domains, not type "+int2str(r.domainType())
55  + " domains.");
56  }
57 
58  // if this is not the last domain, see what is connected on
59  // the right
60  if (m_index + 1 < container().nDomains()) {
61  Domain1D& r = container().domain(m_index+1);
62  if (r.domainType() == cFlowType) {
63  m_flow_right = (StFlow*)&r;
64  m_right_nv = m_flow_right->nComponents();
65  m_right_loc = container().start(m_index+1);
66  m_right_nsp = m_right_nv - 4;
67  m_phase_right = &m_flow_right->phase();
68  } else
69  throw CanteraError("Bdry1D::init",
70  "Boundary domains can only be "
71  "connected on the right to flow domains, not type "+int2str(r.domainType())
72  + " domains.");
73  }
74 }
75 
76 
77 
78 
79 //----------------------------------------------------------
80 //
81 // Inlet1D methods
82 //
83 //----------------------------------------------------------
84 
85 
86 void Inlet1D::
87 setMoleFractions(string xin)
88 {
89  m_xstr = xin;
90  if (m_flow) {
91  m_flow->phase().setMoleFractionsByName(xin);
92  m_flow->phase().getMassFractions(DATA_PTR(m_yin));
93  needJacUpdate();
94  }
95 }
96 
97 void Inlet1D::
98 setMoleFractions(doublereal* xin)
99 {
100  if (m_flow) {
101  m_flow->phase().setMoleFractions(xin);
102  m_flow->phase().getMassFractions(DATA_PTR(m_yin));
103  needJacUpdate();
104  }
105 }
106 
107 string Inlet1D::
108 componentName(size_t n) const
109 {
110  switch (n) {
111  case 0:
112  return "mdot";
113  case 1:
114  return "temperature";
115  default:
116  break;
117  }
118  return "unknown";
119 }
120 
121 void Inlet1D::
123 {
124 
125  _init(2);
126 
127  // set bounds (mdot, T)
128  const doublereal lower[2] = {-1.0e5, 200.0};
129  const doublereal upper[2] = {1.0e5, 1.e5};
130  setBounds(2, lower, 2, upper);
131 
132  // set tolerances
133  vector_fp rtol(2, 1e-4);
134  vector_fp atol(2, 1.e-5);
135  setTolerances(2, DATA_PTR(rtol), 2, DATA_PTR(atol));
136 
137  // if a flow domain is present on the left, then this must be
138  // a right inlet. Note that an inlet object can only be a
139  // terminal object - it cannot have flows on both the left and
140  // right
141  if (m_flow_left) {
142  m_ilr = RightInlet;
143  m_flow = m_flow_left;
144  } else if (m_flow_right) {
145  m_ilr = LeftInlet;
146  m_flow = m_flow_right;
147  } else {
148  throw CanteraError("Inlet1D::init","no flow!");
149  }
150 
151  // components = u, V, T, lambda, + mass fractions
152  m_nsp = m_flow->nComponents() - 4;
153  m_yin.resize(m_nsp, 0.0);
154  if (m_xstr != "") {
155  setMoleFractions(m_xstr);
156  } else {
157  m_yin[0] = 1.0;
158  }
159 }
160 
161 
162 void Inlet1D::
163 eval(size_t jg, doublereal* xg, doublereal* rg,
164  integer* diagg, doublereal rdt)
165 {
166  if (jg != npos && (jg + 2 < firstPoint() || jg > lastPoint() + 2)) {
167  return;
168  }
169 
170  // start of local part of global arrays
171  doublereal* x = xg + loc();
172  doublereal* r = rg + loc();
173  integer* diag = diagg + loc();
174  doublereal* xb, *rb;
175 
176  // residual equations for the two local variables
177 
178  r[0] = m_mdot - x[0];
179 
180  // Temperature
181  r[1] = m_temp - x[1];
182 
183  // both are algebraic constraints
184  diag[0] = 0;
185  diag[1] = 0;
186 
187 
188  // if it is a left inlet, then the flow solution vector
189  // starts 2 to the right in the global solution vector
190  if (m_ilr == LeftInlet) {
191  xb = x + 2;
192  rb = r + 2;
193 
194  // The first flow residual is for u. This, however, is not
195  // modified by the inlet, since this is set within the flow
196  // domain from the continuity equation.
197 
198  // spreading rate. The flow domain sets this to V(0),
199  // so for finite spreading rate subtract m_V0.
200  rb[1] -= m_V0;
201 
202  // The third flow residual is for T, where it is set to
203  // T(0). Subtract the local temperature to hold the flow
204  // T to the inlet T.
205  rb[2] -= x[1];
206 
207  // The flow domain sets this to -rho*u. Add mdot to
208  // specify the mass flow rate.
209  rb[3] += x[0];
210 
211  // add the convective term to the species residual equations
212  for (size_t k = 1; k < m_nsp; k++) {
213  rb[4+k] += x[0]*m_yin[k];
214  }
215 
216  // if the flow is a freely-propagating flame, mdot is not
217  // specified. Set mdot equal to rho*u, and also set
218  // lambda to zero.
219  if (!m_flow->fixed_mdot()) {
220  r[0] = m_flow->density(0)*xb[0] - x[0];
221  rb[3] = xb[3];
222  }
223  }
224 
225  // right inlet.
226  else {
227  size_t boffset = m_flow->nComponents();
228  xb = x - boffset;
229  rb = r - boffset;
230  rb[1] -= m_V0;
231  rb[2] -= x[1]; // T
232  rb[0] += x[0]; // u
233  for (size_t k = 1; k < m_nsp; k++) {
234  rb[4+k] += x[0]*(m_yin[k]);
235  }
236  }
237 
238 
239 }
240 
241 void Inlet1D::
242 save(XML_Node& o, const doublereal* const soln)
243 {
244  const doublereal* s = soln + loc();
245  XML_Node& inlt = o.addChild("domain");
246  inlt.addAttribute("id",id());
247  inlt.addAttribute("points",1);
248  inlt.addAttribute("type","inlet");
249  inlt.addAttribute("components", double(nComponents()));
250  for (size_t k = 0; k < nComponents(); k++) {
251  ctml::addFloat(inlt, componentName(k), s[k], "", "",lowerBound(k), upperBound(k));
252  }
253 }
254 
255 void Inlet1D::
256 restore(const XML_Node& dom, doublereal* soln)
257 {
258  //map<string, double> x;
259  //getFloats(dom, x);
260  soln[0] = ctml::getFloat(dom, "mdot", "massflowrate"); // x["mdot"];
261  soln[1] = ctml::getFloat(dom, "temperature", "temperature"); // x["temperature"];
262  resize(2,1);
263 }
264 
265 
266 
267 //--------------------------------------------------
268 // Empty1D
269 //--------------------------------------------------
270 
271 string Empty1D::componentName(size_t n) const
272 {
273  switch (n) {
274  case 0:
275  return "dummy";
276  default:
277  break;
278  }
279  return "<unknown>";
280 }
281 
282 void Empty1D::
283 init() //_init(1);
284 {
285  // set bounds (T)
286  const doublereal lower = -1.0;
287  const doublereal upper = 1.0;
288  setBounds(1, &lower, 1, &upper);
289 
290  // set tolerances
291  const doublereal rtol = 1e-4;
292  const doublereal atol = 1.e-4;
293  setTolerances(1, &rtol, 1, &atol);
294 }
295 
296 void Empty1D::
297 eval(size_t jg, doublereal* xg, doublereal* rg,
298  integer* diagg, doublereal rdt)
299 {
300  if (jg != npos && (jg + 2 < firstPoint() || jg > lastPoint() + 2)) {
301  return;
302  }
303 
304  // start of local part of global arrays
305  doublereal* x = xg + loc();
306  doublereal* r = rg + loc();
307  integer* diag = diagg + loc();
308  // integer *db;
309 
310  r[0] = x[0];
311  diag[0] = 0;
312 }
313 
314 void Empty1D::
315 save(XML_Node& o, const doublereal* const soln)
316 {
317  XML_Node& symm = o.addChild("domain");
318  symm.addAttribute("id",id());
319  symm.addAttribute("points",1);
320  symm.addAttribute("type","empty");
321  symm.addAttribute("components", double(nComponents()));
322 }
323 
324 void Empty1D::
325 restore(const XML_Node& dom, doublereal* soln)
326 {
327  resize(1,1);
328 }
329 
330 
331 
332 //--------------------------------------------------
333 // Symm1D
334 //--------------------------------------------------
335 
336 string Symm1D::componentName(size_t n) const
337 {
338  switch (n) {
339  case 0:
340  return "dummy";
341  default:
342  break;
343  }
344  return "<unknown>";
345 }
346 
347 void Symm1D::
349 {
350  _init(1);
351  // set bounds (T)
352  const doublereal lower = -1.0;
353  const doublereal upper = 1.0;
354  setBounds(1, &lower, 1, &upper);
355 
356  // set tolerances
357  const doublereal rtol = 1e-4;
358  const doublereal atol = 1.e-4;
359  setTolerances(1, &rtol, 1, &atol);
360 }
361 
362 void Symm1D::
363 eval(size_t jg, doublereal* xg, doublereal* rg,
364  integer* diagg, doublereal rdt)
365 {
366  if (jg != npos && (jg + 2< firstPoint() || jg > lastPoint() + 2)) {
367  return;
368  }
369 
370  // start of local part of global arrays
371  doublereal* x = xg + loc();
372  doublereal* r = rg + loc();
373  integer* diag = diagg + loc();
374  doublereal* xb, *rb;
375  integer* db;
376 
377  r[0] = x[0];
378  diag[0] = 0;
379  size_t nc;
380 
381  if (m_flow_right) {
382  nc = m_flow_right->nComponents();
383  xb = x + 1;
384  rb = r + 1;
385  db = diag + 1;
386  db[1] = 0;
387  db[2] = 0;
388  rb[1] = xb[1] - xb[1 + nc]; // zero dV/dz
389  rb[2] = xb[2] - xb[2 + nc]; // zero dT/dz
390  }
391 
392  if (m_flow_left) {
393  nc = m_flow_left->nComponents();
394  xb = x - nc;
395  rb = r - nc;
396  db = diag - nc;
397  db[1] = 0;
398  db[2] = 0;
399  rb[1] = xb[1] - xb[1 - nc]; // zero dV/dz
400  rb[2] = xb[2] - xb[2 - nc]; // zero dT/dz
401  }
402 }
403 
404 
405 void Symm1D::
406 save(XML_Node& o, const doublereal* const soln)
407 {
408  XML_Node& symm = o.addChild("domain");
409  symm.addAttribute("id",id());
410  symm.addAttribute("points",1);
411  symm.addAttribute("type","symmetry");
412  symm.addAttribute("components", double(nComponents()));
413 }
414 
415 void Symm1D::
416 restore(const XML_Node& dom, doublereal* soln)
417 {
418  resize(1,1);
419 }
420 
421 
422 //--------------------------------------------------
423 // Outlet1D
424 //--------------------------------------------------
425 
426 string Outlet1D::componentName(size_t n) const
427 {
428  switch (n) {
429  case 0:
430  return "outlet dummy";
431  default:
432  break;
433  }
434  return "<unknown>";
435 }
436 
437 void Outlet1D::
438 init()
439 {
440  _init(1);
441  // set bounds (T)
442  const doublereal lower = -1.0;
443  const doublereal upper = 1.0;
444  setBounds(1, &lower, 1, &upper);
445 
446  // set tolerances
447  const doublereal rtol = 1e-4;
448  const doublereal atol = 1.e-4;
449  setTolerances(1, &rtol, 1, &atol);
450  if (m_flow_right) {
451  m_flow_right->setViscosityFlag(false);
452  }
453  if (m_flow_left) {
454  m_flow_left->setViscosityFlag(false);
455  }
456 }
457 
458 
459 void Outlet1D::
460 eval(size_t jg, doublereal* xg, doublereal* rg,
461  integer* diagg, doublereal rdt)
462 {
463  if (jg != npos && (jg + 2 < firstPoint() || jg > lastPoint() + 2)) {
464  return;
465  }
466 
467  // start of local part of global arrays
468  doublereal* x = xg + loc();
469  doublereal* r = rg + loc();
470  integer* diag = diagg + loc();
471  doublereal* xb, *rb;
472  integer* db;
473 
474  r[0] = x[0];
475  diag[0] = 0;
476  size_t nc, k;
477 
478  if (m_flow_right) {
479  nc = m_flow_right->nComponents();
480  xb = x + 1;
481  rb = r + 1;
482  db = diag + 1;
483  rb[0] = xb[3];
484  rb[2] = xb[2] - xb[2 + nc];
485  for (k = 4; k < nc; k++) {
486  //if (m_flow_right->doSpecies(k-4)) {
487  rb[k] = xb[k] - xb[k + nc];
488  //}
489  }
490  }
491 
492  if (m_flow_left) {
493  nc = m_flow_left->nComponents();
494  xb = x - nc;
495  rb = r - nc;
496  db = diag - nc;
497 
498  // zero Lambda
499 
500  if (!m_flow_left->fixed_mdot()) {
501  ; // rb[0] = xb[0] - xb[0-nc]; //zero U gradient
502  } else {
503  rb[0] = xb[3]; // zero Lambda
504  }
505 
506  rb[2] = xb[2] - xb[2 - nc]; // zero T gradient
507  for (k = 5; k < nc; k++) {
508  rb[k] = xb[k] - xb[k - nc]; // zero mass fraction gradient
509  db[k] = 0;
510  }
511  }
512 }
513 
514 
515 void Outlet1D::
516 save(XML_Node& o, const doublereal* const soln)
517 {
518  XML_Node& outlt = o.addChild("domain");
519  outlt.addAttribute("id",id());
520  outlt.addAttribute("points",1);
521  outlt.addAttribute("type","outlet");
522  outlt.addAttribute("components", double(nComponents()));
523 }
524 
525 void Outlet1D::
526 restore(const XML_Node& dom, doublereal* soln)
527 {
528  resize(1,1);
529 }
530 
531 
532 
533 
534 //--------------------------------------------------
535 // OutletRes1D
536 //--------------------------------------------------
537 
538 
539 void OutletRes1D::
540 setMoleFractions(string xres)
541 {
542  m_xstr = xres;
543  if (m_flow) {
544  m_flow->phase().setMoleFractionsByName(xres);
545  m_flow->phase().getMassFractions(DATA_PTR(m_yres));
546  needJacUpdate();
547  }
548 }
549 
550 void OutletRes1D::
551 setMoleFractions(doublereal* xres)
552 {
553  if (m_flow) {
554  m_flow->phase().setMoleFractions(xres);
555  m_flow->phase().getMassFractions(DATA_PTR(m_yres));
556  needJacUpdate();
557  }
558 }
559 
560 string OutletRes1D::componentName(size_t n) const
561 {
562  switch (n) {
563  case 0:
564  return "dummy";
565  default:
566  break;
567  }
568  return "<unknown>";
569 }
570 
571 void OutletRes1D::
573 {
574  _init(1);
575  // set bounds (dummy)
576  const doublereal lower = -1.0;
577  const doublereal upper = 1.0;
578  setBounds(1, &lower, 1, &upper);
579 
580  // set tolerances
581  const doublereal rtol = 1e-4;
582  const doublereal atol = 1.e-4;
583  setTolerances(1, &rtol, 1, &atol);
584 
585  if (m_flow_left) {
586  m_flow = m_flow_left;
587  } else if (m_flow_right) {
588  m_flow = m_flow_right;
589  } else {
590  throw CanteraError("OutletRes1D::init","no flow!");
591  }
592 
593  m_nsp = m_flow->nComponents() - 4;
594  m_yres.resize(m_nsp, 0.0);
595  if (m_xstr != "") {
596  setMoleFractions(m_xstr);
597  } else {
598  m_yres[0] = 1.0;
599  }
600 }
601 
602 
603 void OutletRes1D::
604 eval(size_t jg, doublereal* xg, doublereal* rg,
605  integer* diagg, doublereal rdt)
606 {
607 
608  if (jg != npos && (jg + 2 < firstPoint() || jg > lastPoint() + 2)) {
609  return;
610  }
611 
612  // start of local part of global arrays
613  doublereal* x = xg + loc();
614  doublereal* r = rg + loc();
615  integer* diag = diagg + loc();
616  doublereal* xb, *rb;
617  integer* db;
618 
619  // drive dummy component to zero
620  r[0] = x[0];
621  diag[0] = 0;
622  size_t nc, k;
623 
624  if (m_flow_right) {
625  nc = m_flow_right->nComponents();
626  xb = x + 1;
627  rb = r + 1;
628  db = diag + 1;
629 
630  // this seems wrong...
631  // zero Lambda
632  rb[0] = xb[3];
633 
634  // zero gradient for T
635  rb[2] = xb[2] - xb[2 + nc];
636 
637  // specified mass fractions
638  for (k = 4; k < nc; k++) {
639  rb[k] = xb[k] - m_yres[k-4];
640  }
641  }
642 
643  if (m_flow_left) {
644 
645  nc = m_flow_left->nComponents();
646  xb = x - nc;
647  rb = r - nc;
648  db = diag - nc;
649 
650  if (!m_flow_left->fixed_mdot()) {
651  ;
652  } else {
653  rb[0] = xb[3]; // zero Lambda
654  }
655  rb[2] = xb[2] - m_temp; //xb[2] - xb[2 - nc]; // zero dT/dz
656  for (k = 5; k < nc; k++) {
657  rb[k] = xb[k] - m_yres[k-4]; // fixed Y
658  db[k] = 0;
659  }
660  }
661 }
662 
663 
664 void OutletRes1D::
665 save(XML_Node& o, const doublereal* const soln)
666 {
667  XML_Node& outlt = o.addChild("domain");
668  outlt.addAttribute("id",id());
669  outlt.addAttribute("points",1);
670  outlt.addAttribute("type","outletres");
671  outlt.addAttribute("components", double(nComponents()));
672 }
673 
674 void OutletRes1D::
675 restore(const XML_Node& dom, doublereal* soln)
676 {
677  resize(1,1);
678 }
679 
680 
681 //-----------------------------------------------------------
682 //
683 // Surf1D
684 //
685 //-----------------------------------------------------------
686 
687 
688 
689 string Surf1D::componentName(size_t n) const
690 {
691  switch (n) {
692  case 0:
693  return "temperature";
694  default:
695  break;
696  }
697  return "<unknown>";
698 }
699 
700 void Surf1D::
702 {
703  _init(1);
704  // set bounds (T)
705  const doublereal lower = 200.0;
706  const doublereal upper = 1.e5;
707  setBounds(1, &lower, 1, &upper);
708 
709  // set tolerances
710  const doublereal rtol = 1e-4;
711  const doublereal atol = 1.e-4;
712  setTolerances(1, &rtol, 1, &atol);
713 }
714 
715 
716 void Surf1D::
717 eval(size_t jg, doublereal* xg, doublereal* rg,
718  integer* diagg, doublereal rdt)
719 {
720  if (jg != npos && (jg + 2 < firstPoint() || jg > lastPoint() + 2)) {
721  return;
722  }
723 
724  // start of local part of global arrays
725  doublereal* x = xg + loc();
726  doublereal* r = rg + loc();
727  integer* diag = diagg + loc();
728  doublereal* xb, *rb;
729 
730  r[0] = x[0] - m_temp;
731  diag[0] = 0;
732  size_t nc;
733 
734  if (m_flow_right) {
735  rb = r + 1;
736  xb = x + 1;
737  rb[2] = xb[2] - x[0]; // specified T
738  }
739 
740  if (m_flow_left) {
741  nc = m_flow_left->nComponents();
742  rb = r - nc;
743  xb = x - nc;
744  rb[2] = xb[2] - x[0]; // specified T
745  }
746 }
747 
748 void Surf1D::
749 save(XML_Node& o, const doublereal* const soln)
750 {
751  const doublereal* s = soln + loc();
752  //XML_Node& inlt = o.addChild("inlet");
753  XML_Node& inlt = o.addChild("domain");
754  inlt.addAttribute("id",id());
755  inlt.addAttribute("points",1);
756  inlt.addAttribute("type","surface");
757  inlt.addAttribute("components", double(nComponents()));
758  for (size_t k = 0; k < nComponents(); k++) {
759  ctml::addFloat(inlt, componentName(k), s[k], "", "",0.0, 1.0);
760  }
761 }
762 
763 void Surf1D::
764 restore(const XML_Node& dom, doublereal* soln)
765 {
766  map<string, double> x;
767  ctml::getFloats(dom, x);
768  soln[0] = x["temperature"];
769  resize(1,1);
770 }
771 
772 
773 
774 
775 //-----------------------------------------------------------
776 //
777 // ReactingSurf1D
778 //
779 //-----------------------------------------------------------
780 
781 
782 
783 string ReactingSurf1D::componentName(size_t n) const
784 {
785  if (n == 0) {
786  return "temperature";
787  } else if (n < m_nsp + 1) {
788  return m_sphase->speciesName(n-1);
789  } else {
790  return "<unknown>";
791  }
792 }
793 
794 void ReactingSurf1D::
796 {
797  m_nv = m_nsp + 1;
798  _init(m_nsp+1);
799  m_fixed_cov.resize(m_nsp, 0.0);
800  m_fixed_cov[0] = 1.0;
801  m_work.resize(m_kin->nTotalSpecies(), 0.0);
802 
803  // set bounds
804  vector_fp lower(m_nv), upper(m_nv);
805  lower[0] = 200.0;
806  upper[0] = 1.e5;
807  for (size_t n = 0; n < m_nsp; n++) {
808  lower[n+1] = -1.0e-5;
809  upper[n+1] = 2.0;
810  }
811  setBounds(m_nv, DATA_PTR(lower), m_nv, DATA_PTR(upper));
812  vector_fp rtol(m_nv), atol(m_nv);
813  for (size_t n = 0; n < m_nv; n++) {
814  rtol[n] = 1.0e-5;
815  atol[n] = 1.0e-9;
816  }
817  atol[0] = 1.0e-4;
818  setTolerances(m_nv, DATA_PTR(rtol), m_nv, DATA_PTR(atol));
819 }
820 
821 
822 void ReactingSurf1D::
823 eval(size_t jg, doublereal* xg, doublereal* rg,
824  integer* diagg, doublereal rdt)
825 {
826  if (jg != npos && (jg + 2 < firstPoint() || jg > lastPoint() + 2)) {
827  return;
828  }
829 
830  // start of local part of global arrays
831  doublereal* x = xg + loc();
832  doublereal* r = rg + loc();
833  integer* diag = diagg + loc();
834  doublereal* xb, *rb;
835 
836  // specified surface temp
837  r[0] = x[0] - m_temp;
838 
839  // set the coverages
840  doublereal sum = 0.0;
841  for (size_t k = 0; k < m_nsp; k++) {
842  m_work[k] = x[k+1];
843  sum += x[k+1];
844  }
845  m_sphase->setTemperature(x[0]);
846  m_sphase->setCoverages(DATA_PTR(m_work));
847  //m_kin->advanceCoverages(1.0);
848  //m_sphase->getCoverages(m_fixed_cov.begin());
849 
850  // set the left gas state to the adjacent point
851 
852  size_t leftloc = 0, rightloc = 0;
853  size_t pnt = 0;
854 
855  if (m_flow_left) {
856  leftloc = m_flow_left->loc();
857  pnt = m_flow_left->nPoints() - 1;
858  m_flow_left->setGas(xg + leftloc, pnt);
859  }
860 
861  if (m_flow_right) {
862  rightloc = m_flow_right->loc();
863  m_flow_right->setGas(xg + rightloc, 0);
864  }
865 
866  m_kin->getNetProductionRates(DATA_PTR(m_work));
867  doublereal rs0 = 1.0/m_sphase->siteDensity();
868 
869  //scale(m_work.begin(), m_work.end(), m_work.begin(), m_mult[0]);
870 
871  // bool enabled = true;
872  size_t ioffset = m_kin->kineticsSpeciesIndex(0, m_surfindex);
873 
874  if (m_enabled) {
875  doublereal maxx = -1.0;
876  for (size_t k = 0; k < m_nsp; k++) {
877  r[k+1] = m_work[k + ioffset] * m_sphase->size(k) * rs0;
878  r[k+1] -= rdt*(x[k+1] - prevSoln(k+1,0));
879  diag[k+1] = 1;
880  if (x[k+1] > maxx) {
881  maxx = x[k+1];
882  }
883  }
884  r[1] = 1.0 - sum;
885  diag[1] = 0;
886  } else {
887  for (size_t k = 0; k < m_nsp; k++) {
888  r[k+1] = x[k+1] - m_fixed_cov[k];
889  diag[k+1] = 0;
890  }
891  }
892 
893  if (m_flow_right) {
894  rb = r + 1;
895  xb = x + 1;
896  rb[2] = xb[2] - x[0]; // specified T
897  }
898  size_t nc;
899  if (m_flow_left) {
900  nc = m_flow_left->nComponents();
901  const doublereal* mwleft = DATA_PTR(m_phase_left->molecularWeights());
902  rb =r - nc;
903  xb = x - nc;
904  rb[2] = xb[2] - x[0]; // specified T
905  for (size_t nl = 1; nl < m_left_nsp; nl++) {
906  rb[4+nl] += m_work[nl]*mwleft[nl];
907  }
908  }
909 }
910 
911 void ReactingSurf1D::
912 save(XML_Node& o, const doublereal* const soln)
913 {
914  const doublereal* s = soln + loc();
915  //XML_Node& inlt = o.addChild("inlet");
916  XML_Node& inlt = o.addChild("domain");
917  inlt.addAttribute("id",id());
918  inlt.addAttribute("points",1);
919  inlt.addAttribute("type","surface");
920  inlt.addAttribute("components", double(nComponents()));
921  for (size_t k = 0; k < nComponents(); k++) {
922  ctml::addFloat(inlt, componentName(k), s[k], "", "",0.0, 1.0);
923  }
924 }
925 
926 void ReactingSurf1D::
927 restore(const XML_Node& dom, doublereal* soln)
928 {
929  map<string, double> x;
930  ctml::getFloats(dom, x);
931  soln[0] = x["temperature"];
932  resize(1,1);
933 }
934 }
935