Cantera  3.1.0a1
Boundary1D.cpp
Go to the documentation of this file.
1 //! @file Boundary1D.cpp
2 
3 // This file is part of Cantera. See License.txt in the top-level directory or
4 // at https://cantera.org/license.txt for license and copyright information.
5 
8 #include "cantera/oneD/OneDim.h"
9 #include "cantera/oneD/StFlow.h"
10 
11 using namespace std;
12 
13 namespace Cantera
14 {
15 
16 Boundary1D::Boundary1D() : Domain1D(1, 1, 0.0)
17 {
18 }
19 
20 void Boundary1D::_init(size_t n)
21 {
22  if (m_index == npos) {
23  throw CanteraError("Boundary1D::_init",
24  "install in container before calling init.");
25  }
26 
27  // A boundary object contains only one grid point
28  resize(n,1);
29 
30  m_left_nsp = 0;
31  m_right_nsp = 0;
32 
33  // check for left and right flow objects
34  if (m_index > 0) {
35  Domain1D& r = container().domain(m_index-1);
36  if (!r.isConnector()) { // multi-point domain
37  m_left_nv = r.nComponents();
38  if (m_left_nv > c_offset_Y) {
39  m_left_nsp = m_left_nv - c_offset_Y;
40  } else {
41  m_left_nsp = 0;
42  }
43  m_left_loc = container().start(m_index-1);
44  m_left_points = r.nPoints();
45  m_flow_left = dynamic_cast<StFlow*>(&r);
46  if (m_flow_left != nullptr) {
47  m_phase_left = &m_flow_left->phase();
48  }
49  } else {
50  throw CanteraError("Boundary1D::_init",
51  "Boundary domains can only be connected on the left to flow "
52  "domains, not '{}' domains.", r.type());
53  }
54  }
55 
56  // if this is not the last domain, see what is connected on the right
57  if (m_index + 1 < container().nDomains()) {
58  Domain1D& r = container().domain(m_index+1);
59  if (!r.isConnector()) { // multi-point domain
60  m_right_nv = r.nComponents();
61  if (m_right_nv > c_offset_Y) {
62  m_right_nsp = m_right_nv - c_offset_Y;
63  } else {
64  m_right_nsp = 0;
65  }
66  m_right_loc = container().start(m_index+1);
67  m_flow_right = dynamic_cast<StFlow*>(&r);
68  if (m_flow_right != nullptr) {
69  m_phase_right = &m_flow_right->phase();
70  }
71  } else {
72  throw CanteraError("Boundary1D::_init",
73  "Boundary domains can only be connected on the right to flow "
74  "domains, not '{}' domains.", r.type());
75  }
76  }
77 }
78 
79 void Boundary1D::fromArray(SolutionArray& arr, double* soln)
80 {
81  setMeta(arr.meta());
82 }
83 
84 // ---------------- Inlet1D methods ----------------
85 
86 Inlet1D::Inlet1D()
87 {
88 }
89 
90 Inlet1D::Inlet1D(shared_ptr<Solution> solution, const string& id)
91  : Inlet1D()
92 {
94  m_id = id;
95 }
96 
97 
98 //! set spreading rate
99 void Inlet1D::setSpreadRate(double V0)
100 {
101  m_V0 = V0;
102  needJacUpdate();
103 }
104 
105 
106 void Inlet1D::show(const double* x)
107 {
108  writelog(" Mass Flux: {:10.4g} kg/m^2/s \n", m_mdot);
109  writelog(" Temperature: {:10.4g} K \n", m_temp);
110  if (m_flow) {
111  writelog(" Mass Fractions: \n");
112  for (size_t k = 0; k < m_flow->phase().nSpecies(); k++) {
113  if (m_yin[k] != 0.0) {
114  writelog(" {:>16s} {:10.4g} \n",
115  m_flow->phase().speciesName(k), m_yin[k]);
116  }
117  }
118  }
119  writelog("\n");
120 }
121 
122 void Inlet1D::setMoleFractions(const string& xin)
123 {
124  m_xstr = xin;
125  if (m_flow) {
126  m_flow->phase().setMoleFractionsByName(xin);
127  m_flow->phase().getMassFractions(m_yin.data());
128  needJacUpdate();
129  }
130 }
131 
132 void Inlet1D::setMoleFractions(const double* xin)
133 {
134  if (m_flow) {
135  m_flow->phase().setMoleFractions(xin);
136  m_flow->phase().getMassFractions(m_yin.data());
137  needJacUpdate();
138  }
139 }
140 
142 {
143  _init(0);
144 
145  // if a flow domain is present on the left, then this must be a right inlet.
146  // Note that an inlet object can only be a terminal object - it cannot have
147  // flows on both the left and right
148  if (m_flow_left && !m_flow_right) {
149  if (!m_flow_left->isStrained()) {
150  throw CanteraError("Inlet1D::init",
151  "Right inlets with right-to-left flow are only supported for "
152  "strained flow configurations.");
153  }
154  m_ilr = RightInlet;
155  m_flow = m_flow_left;
156  } else if (m_flow_right) {
157  m_ilr = LeftInlet;
158  m_flow = m_flow_right;
159  } else {
160  throw CanteraError("Inlet1D::init", "Inlet1D is not properly connected.");
161  }
162 
163  // components = u, V, T, lambda, + mass fractions
164  m_nsp = m_flow->phase().nSpecies();
165  m_yin.resize(m_nsp, 0.0);
166  if (m_xstr != "") {
167  setMoleFractions(m_xstr);
168  } else {
169  m_yin[0] = 1.0;
170  }
171 }
172 
173 void Inlet1D::eval(size_t jg, double* xg, double* rg,
174  integer* diagg, double rdt)
175 {
176  if (jg != npos && (jg + 2 < firstPoint() || jg > lastPoint() + 2)) {
177  return;
178  }
179 
180  if (m_ilr == LeftInlet) {
181  // Array elements corresponding to the first point of the flow domain
182  double* xb = xg + m_flow->loc();
183  double* rb = rg + m_flow->loc();
184 
185  // The first flow residual is for u. This, however, is not modified by
186  // the inlet, since this is set within the flow domain from the
187  // continuity equation.
188 
189  if (m_flow->doEnergy(0)) {
190  // The third flow residual is for T, where it is set to T(0). Subtract
191  // the local temperature to hold the flow T to the inlet T.
192  rb[c_offset_T] -= m_temp;
193  } else {
194  rb[c_offset_T] -= m_flow->T_fixed(0);
195  }
196 
197  if (m_flow->isFree()) {
198  // if the flow is a freely-propagating flame, mdot is not specified.
199  // Set mdot equal to rho*u, and also set lambda to zero.
200  m_mdot = m_flow->density(0) * xb[c_offset_U];
201  rb[c_offset_L] = xb[c_offset_L];
202  } else if (m_flow->isStrained()) {
203  // The flow domain sets this to -rho*u. Add mdot to specify the mass
204  // flow rate
205  rb[c_offset_L] += m_mdot;
206 
207  // spreading rate. The flow domain sets this to V(0),
208  // so for finite spreading rate subtract m_V0.
209  rb[c_offset_V] -= m_V0;
210  } else {
211  rb[c_offset_U] = m_flow->density(0) * xb[c_offset_U] - m_mdot;
212  rb[c_offset_L] = xb[c_offset_L];
213  }
214 
215  // add the convective term to the species residual equations
216  for (size_t k = 0; k < m_nsp; k++) {
217  if (k != m_flow_right->leftExcessSpecies()) {
218  rb[c_offset_Y+k] += m_mdot*m_yin[k];
219  }
220  }
221 
222  } else {
223  // right inlet (should only be used for counter-flow flames)
224  // Array elements corresponding to the last point in the flow domain
225  double* rb = rg + loc() - m_flow->nComponents();
226  rb[c_offset_V] -= m_V0;
227  if (m_flow->doEnergy(m_flow->nPoints() - 1)) {
228  rb[c_offset_T] -= m_temp; // T
229  } else {
230  rb[c_offset_T] -= m_flow->T_fixed(m_flow->nPoints() - 1);
231  }
232  rb[c_offset_U] += m_mdot; // u
233  for (size_t k = 0; k < m_nsp; k++) {
234  if (k != m_flow_left->rightExcessSpecies()) {
235  rb[c_offset_Y+k] += m_mdot * m_yin[k];
236  }
237  }
238  }
239 }
240 
241 shared_ptr<SolutionArray> Inlet1D::asArray(const double* soln) const
242 {
243  AnyMap meta = Boundary1D::getMeta();
244  meta["mass-flux"] = m_mdot;
245  auto arr = SolutionArray::create(m_solution, 1, meta);
246 
247  // set gas state (using pressure from adjacent domain)
248  double pressure = m_flow->phase().pressure();
249  auto phase = m_solution->thermo();
250  phase->setState_TPY(m_temp, pressure, m_yin.data());
251  vector<double> data(phase->stateSize());
252  phase->saveState(data);
253 
254  arr->setState(0, data);
255  return arr;
256 }
257 
258 void Inlet1D::fromArray(SolutionArray& arr, double* soln)
259 {
260  Boundary1D::setMeta(arr.meta());
261  arr.setLoc(0);
262  auto phase = arr.thermo();
263  auto meta = arr.meta();
264  m_temp = phase->temperature();
265  if (meta.hasKey("mass-flux")) {
266  m_mdot = meta.at("mass-flux").asDouble();
267  } else {
268  // convert data format used by Python h5py export (Cantera < 3.0)
269  auto aux = arr.getAuxiliary(0);
270  m_mdot = phase->density() * aux.at("velocity").as<double>();
271  }
272  phase->getMassFractions(m_yin.data());
273 }
274 
275 // ------------- Empty1D -------------
276 
278 {
279  _init(0);
280 }
281 
282 void Empty1D::eval(size_t jg, double* xg, double* rg,
283  integer* diagg, double rdt)
284 {
285 }
286 
287 shared_ptr<SolutionArray> Empty1D::asArray(const double* soln) const
288 {
289  AnyMap meta = Boundary1D::getMeta();
290  return SolutionArray::create(m_solution, 0, meta);
291 }
292 
293 // -------------- Symm1D --------------
294 
296 {
297  _init(0);
298 }
299 
300 void Symm1D::eval(size_t jg, double* xg, double* rg, integer* diagg,
301  double rdt)
302 {
303  if (jg != npos && (jg + 2< firstPoint() || jg > lastPoint() + 2)) {
304  return;
305  }
306 
307  // start of local part of global arrays
308  double* x = xg + loc();
309  double* r = rg + loc();
310  integer* diag = diagg + loc();
311 
312  if (m_flow_right) {
313  size_t nc = m_flow_right->nComponents();
314  double* xb = x;
315  double* rb = r;
316  int* db = diag;
317  db[c_offset_V] = 0;
318  db[c_offset_T] = 0;
319  rb[c_offset_V] = xb[c_offset_V] - xb[c_offset_V + nc]; // zero dV/dz
320  if (m_flow_right->doEnergy(0)) {
321  rb[c_offset_T] = xb[c_offset_T] - xb[c_offset_T + nc]; // zero dT/dz
322  }
323  }
324 
325  if (m_flow_left) {
326  size_t nc = m_flow_left->nComponents();
327  double* xb = x - nc;
328  double* rb = r - nc;
329  int* db = diag - nc;
330  db[c_offset_V] = 0;
331  db[c_offset_T] = 0;
332  rb[c_offset_V] = xb[c_offset_V] - xb[c_offset_V - nc]; // zero dV/dz
333  if (m_flow_left->doEnergy(m_flow_left->nPoints() - 1)) {
334  rb[c_offset_T] = xb[c_offset_T] - xb[c_offset_T - nc]; // zero dT/dz
335  }
336  }
337 }
338 
339 shared_ptr<SolutionArray> Symm1D::asArray(const double* soln) const
340 {
341  AnyMap meta = Boundary1D::getMeta();
342  return SolutionArray::create(m_solution, 0, meta);
343 }
344 
345 // -------- Outlet1D --------
346 
347 OutletRes1D::OutletRes1D()
348 {
349 }
350 
351 OutletRes1D::OutletRes1D(shared_ptr<Solution> solution, const string& id)
352  : OutletRes1D()
353 {
355  m_id = id;
356 }
357 
359 {
360  _init(0);
361 
362  if (m_flow_right) {
363  throw CanteraError("Outlet1D::init",
364  "Left outlets with right-to-left flow are not supported.");
365  }
366  if (m_flow_left) {
367  m_flow_left->setViscosityFlag(false);
368  } else {
369  throw CanteraError("Outlet1D::init", "Outlet1D is not connected.");
370  }
371 }
372 
373 void Outlet1D::eval(size_t jg, double* xg, double* rg, integer* diagg,
374  double rdt)
375 {
376  if (jg != npos && (jg + 2 < firstPoint() || jg > lastPoint() + 2)) {
377  return;
378  }
379 
380  // start of local part of global arrays
381  double* x = xg + loc();
382  double* r = rg + loc();
383  integer* diag = diagg + loc();
384 
385  // flow is left-to-right
386  size_t nc = m_flow_left->nComponents();
387  double* xb = x - nc;
388  double* rb = r - nc;
389  int* db = diag - nc;
390 
391  size_t last = m_flow_left->nPoints() - 1;
392  if (m_flow_left->doEnergy(last)) {
393  rb[c_offset_T] = xb[c_offset_T] - xb[c_offset_T - nc]; // zero T gradient
394  } else {
395  rb[c_offset_T] = xb[c_offset_T] - m_flow_left->T_fixed(last);
396  }
397  size_t kSkip = c_offset_Y + m_flow_left->rightExcessSpecies();
398  for (size_t k = c_offset_Y; k < nc; k++) {
399  if (k != kSkip) {
400  rb[k] = xb[k] - xb[k - nc]; // zero mass fraction gradient
401  db[k] = 0;
402  }
403  }
404 }
405 
406 shared_ptr<SolutionArray> Outlet1D::asArray(const double* soln) const
407 {
408  AnyMap meta = Boundary1D::getMeta();
409  return SolutionArray::create(m_solution, 0, meta);
410 }
411 
412 // -------- OutletRes1D --------
413 
414 void OutletRes1D::setMoleFractions(const string& xres)
415 {
416  m_xstr = xres;
417  if (m_flow) {
418  m_flow->phase().setMoleFractionsByName(xres);
419  m_flow->phase().getMassFractions(m_yres.data());
420  needJacUpdate();
421  }
422 }
423 
424 void OutletRes1D::setMoleFractions(const double* xres)
425 {
426  if (m_flow) {
427  m_flow->phase().setMoleFractions(xres);
428  m_flow->phase().getMassFractions(m_yres.data());
429  needJacUpdate();
430  }
431 }
432 
434 {
435  _init(0);
436 
437  if (m_flow_right) {
438  throw CanteraError("OutletRes1D::init",
439  "Left outlets with right-to-left flow are not supported.");
440  }
441  if (m_flow_left) {
442  m_flow = m_flow_left;
443  } else {
444  throw CanteraError("OutletRes1D::init", "no flow!");
445  }
446 
447  m_nsp = m_flow->phase().nSpecies();
448  m_yres.resize(m_nsp, 0.0);
449  if (m_xstr != "") {
450  setMoleFractions(m_xstr);
451  } else {
452  m_yres[0] = 1.0;
453  }
454 }
455 
456 void OutletRes1D::eval(size_t jg, double* xg, double* rg,
457  integer* diagg, double rdt)
458 {
459  if (jg != npos && (jg + 2 < firstPoint() || jg > lastPoint() + 2)) {
460  return;
461  }
462 
463  // start of local part of global arrays
464  double* x = xg + loc();
465  double* r = rg + loc();
466  integer* diag = diagg + loc();
467 
468  size_t nc = m_flow_left->nComponents();
469  double* xb = x - nc;
470  double* rb = r - nc;
471  int* db = diag - nc;
472 
473  size_t last = m_flow_left->nPoints() - 1;
474  if (m_flow_left->doEnergy(last)) {
475  rb[c_offset_T] = xb[c_offset_T] - xb[c_offset_T - nc]; // zero T gradient
476  } else {
477  rb[c_offset_T] = xb[c_offset_T] - m_flow_left->T_fixed(last);
478  }
479  size_t kSkip = m_flow_left->rightExcessSpecies();
480  for (size_t k = c_offset_Y; k < nc; k++) {
481  if (k != kSkip) {
482  rb[k] = xb[k] - m_yres[k-c_offset_Y]; // fixed Y
483  db[k] = 0;
484  }
485  }
486 }
487 
488 shared_ptr<SolutionArray> OutletRes1D::asArray(const double* soln) const
489 {
490  AnyMap meta = Boundary1D::getMeta();
491  meta["temperature"] = m_temp;
492  auto arr = SolutionArray::create(m_solution, 1, meta);
493 
494  // set gas state (using pressure from adjacent domain)
495  double pressure = m_flow->phase().pressure();
496  auto phase = m_solution->thermo();
497  phase->setState_TPY(m_temp, pressure, &m_yres[0]);
498  vector<double> data(phase->stateSize());
499  phase->saveState(data);
500 
501  arr->setState(0, data);
502  return arr;
503 }
504 
505 void OutletRes1D::fromArray(SolutionArray& arr, double* soln)
506 {
507  Boundary1D::setMeta(arr.meta());
508  arr.setLoc(0);
509  auto phase = arr.thermo();
510  m_temp = phase->temperature();
511  auto Y = phase->massFractions();
512  std::copy(Y, Y + m_nsp, &m_yres[0]);
513 }
514 
515 // -------- Surf1D --------
516 
518 {
519  _init(0);
520 }
521 
522 void Surf1D::eval(size_t jg, double* xg, double* rg,
523  integer* diagg, double rdt)
524 {
525  if (jg != npos && (jg + 2 < firstPoint() || jg > lastPoint() + 2)) {
526  return;
527  }
528 
529  // start of local part of global arrays
530  double* x = xg + loc();
531  double* r = rg + loc();
532 
533  if (m_flow_right) {
534  double* rb = r;
535  double* xb = x;
536  rb[c_offset_T] = xb[c_offset_T] - m_temp; // specified T
537  }
538 
539  if (m_flow_left) {
540  size_t nc = m_flow_left->nComponents();
541  double* rb = r - nc;
542  double* xb = x - nc;
543  rb[c_offset_T] = xb[c_offset_T] - m_temp; // specified T
544  }
545 }
546 
547 shared_ptr<SolutionArray> Surf1D::asArray(const double* soln) const
548 {
549  AnyMap meta = Boundary1D::getMeta();
550  meta["temperature"] = m_temp;
551  return SolutionArray::create(m_solution, 0, meta);
552 }
553 
554 void Surf1D::fromArray(SolutionArray& arr, double* soln)
555 {
556  auto meta = arr.meta();
557  m_temp = meta["temperature"].asDouble();
558  meta.erase("temperature");
559  Boundary1D::setMeta(meta);
560 }
561 
562 void Surf1D::show(std::ostream& s, const double* x)
563 {
564  s << "------------------- Surface " << domainIndex() << " ------------------- " << std::endl;
565  s << " temperature: " << m_temp << " K" << std::endl;
566 }
567 
568 void Surf1D::show(const double* x)
569 {
570  writelog(" Temperature: {:10.4g} K \n\n", m_temp);
571 }
572 
573 // -------- ReactingSurf1D --------
574 
575 ReactingSurf1D::ReactingSurf1D()
576  : m_kin(0)
577  , m_nsp(0)
578 {
579 }
580 
581 ReactingSurf1D::ReactingSurf1D(shared_ptr<Solution> solution, const string& id)
582 {
583  auto phase = std::dynamic_pointer_cast<SurfPhase>(solution->thermo());
584  if (!phase) {
585  throw CanteraError("ReactingSurf1D::ReactingSurf1D",
586  "Detected incompatible ThermoPhase type '{}'", solution->thermo()->type());
587  }
588  auto kin = std::dynamic_pointer_cast<InterfaceKinetics>(solution->kinetics());
589  if (!kin) {
590  throw CanteraError("ReactingSurf1D::ReactingSurf1D",
591  "Detected incompatible kinetics type '{}'",
592  solution->kinetics()->kineticsType());
593  }
595  m_id = id;
596  m_kin = kin.get();
597  m_sphase = phase.get();
598  m_nsp = m_sphase->nSpecies();
599  m_enabled = true;
600 }
601 
602 void ReactingSurf1D::setKinetics(shared_ptr<Kinetics> kin)
603 {
605  m_solution->setThermo(kin->reactionPhase());
606  m_solution->setKinetics(kin);
607  m_solution->setTransportModel("none");
608  m_kin = dynamic_pointer_cast<InterfaceKinetics>(kin).get();
609  m_sphase = dynamic_pointer_cast<SurfPhase>(kin->reactionPhase()).get();
610  m_nsp = m_sphase->nSpecies();
611  m_enabled = true;
612 }
613 
614 string ReactingSurf1D::componentName(size_t n) const
615 {
616  if (n < m_nsp) {
617  return m_sphase->speciesName(n);
618  } else {
619  return "<unknown>";
620  }
621 }
622 
624 {
625  m_nv = m_nsp;
626  _init(m_nsp);
627 
628  m_fixed_cov.resize(m_nsp, 0.0);
629  m_fixed_cov[0] = 1.0;
630  m_work.resize(m_kin->nTotalSpecies(), 0.0);
631 
632  for (size_t n = 0; n < m_nsp; n++) {
633  setBounds(n, -1.0e-5, 2.0);
634  }
635 }
636 
638  double* x = xg + loc();
639  m_sphase->setCoverages(x);
640  m_sphase->getCoverages(x);
641 }
642 
643 void ReactingSurf1D::eval(size_t jg, double* xg, double* rg,
644  integer* diagg, double rdt)
645 {
646  if (jg != npos && (jg + 2 < firstPoint() || jg > lastPoint() + 2)) {
647  return;
648  }
649 
650  // start of local part of global arrays
651  double* x = xg + loc();
652  double* r = rg + loc();
653  integer* diag = diagg + loc();
654 
655  // set the coverages
656  double sum = 0.0;
657  for (size_t k = 0; k < m_nsp; k++) {
658  m_work[k] = x[k];
659  sum += x[k];
660  }
661  m_sphase->setTemperature(m_temp);
662  m_sphase->setCoveragesNoNorm(m_work.data());
663 
664  // set the left gas state to the adjacent point
665 
666  size_t leftloc = 0, rightloc = 0;
667  size_t pnt = 0;
668 
669  if (m_flow_left) {
670  leftloc = m_flow_left->loc();
671  pnt = m_flow_left->nPoints() - 1;
672  m_flow_left->setGas(xg + leftloc, pnt);
673  }
674 
675  if (m_flow_right) {
676  rightloc = m_flow_right->loc();
677  m_flow_right->setGas(xg + rightloc, 0);
678  }
679 
680  m_kin->getNetProductionRates(m_work.data());
681  double rs0 = 1.0/m_sphase->siteDensity();
682 
683  if (m_enabled) {
684  for (size_t k = 0; k < m_nsp; k++) {
685  r[k] = m_work[k] * m_sphase->size(k) * rs0;
686  r[k] -= rdt*(x[k] - prevSoln(k,0));
687  diag[k] = 1;
688  }
689  r[0] = 1.0 - sum;
690  diag[0] = 0;
691  } else {
692  for (size_t k = 0; k < m_nsp; k++) {
693  r[k] = x[k] - m_fixed_cov[k];
694  diag[k] = 0;
695  }
696  }
697 
698  if (m_flow_right) {
699  double* rb = r + m_nsp;
700  double* xb = x + m_nsp;
701  rb[c_offset_T] = xb[c_offset_T] - m_temp; // specified T
702  }
703  if (m_flow_left) {
704  size_t nc = m_flow_left->nComponents();
705  const vector<double>& mwleft = m_phase_left->molecularWeights();
706  double* rb = r - nc;
707  double* xb = x - nc;
708  rb[c_offset_T] = xb[c_offset_T] - m_temp; // specified T
709  size_t nSkip = m_flow_left->rightExcessSpecies();
710  size_t l_offset = 0;
711  ThermoPhase* left_thermo = &m_flow_left->phase();
712  for (size_t nth = 0; nth < m_kin->nPhases(); nth++) {
713  if (&m_kin->thermo(nth) == left_thermo) {
714  l_offset = m_kin->kineticsSpeciesIndex(0, nth);
715  break;
716  }
717  }
718  for (size_t nl = 0; nl < m_left_nsp; nl++) {
719  if (nl != nSkip) {
720  rb[c_offset_Y+nl] += m_work[nl + l_offset]*mwleft[nl];
721  }
722  }
723  }
724 }
725 
726 shared_ptr<SolutionArray> ReactingSurf1D::asArray(const double* soln) const
727 {
728  AnyMap meta = Boundary1D::getMeta();
729  meta["temperature"] = m_temp;
730  meta["phase"]["name"] = m_sphase->name();
731  AnyValue source = m_sphase->input().getMetadata("filename");
732  meta["phase"]["source"] = source.empty() ? "<unknown>" : source.asString();
733 
734  // set state of surface phase
735  m_sphase->setState_TP(m_temp, m_sphase->pressure());
736  m_sphase->setCoverages(soln);
737  vector<double> data(m_sphase->stateSize());
738  m_sphase->saveState(data.size(), &data[0]);
739 
740  auto arr = SolutionArray::create(m_solution, 1, meta);
741  arr->setState(0, data);
742  return arr;
743 }
744 
745 void ReactingSurf1D::fromArray(SolutionArray& arr, double* soln)
746 {
747  Boundary1D::setMeta(arr.meta());
748  arr.setLoc(0);
749  auto surf = std::dynamic_pointer_cast<SurfPhase>(arr.thermo());
750  if (!surf) {
751  throw CanteraError("ReactingSurf1D::fromArray",
752  "Restoring of coverages requires surface phase");
753  }
754  m_temp = surf->temperature();
755  surf->getCoverages(soln);
756 }
757 
758 void ReactingSurf1D::show(const double* x)
759 {
760  writelog(" Temperature: {:10.4g} K \n", m_temp);
761  writelog(" Coverages: \n");
762  for (size_t k = 0; k < m_nsp; k++) {
763  writelog(" {:>20s} {:10.4g} \n", m_sphase->speciesName(k), x[k]);
764  }
765  writelog("\n");
766 }
767 }
Boundary objects for one-dimensional simulations.
const AnyValue & getMetadata(const string &key) const
Get a value from the metadata applicable to the AnyMap tree containing this node.
Definition: AnyMap.cpp:580
A map of string keys to values whose type can vary at runtime.
Definition: AnyMap.h:427
A wrapper for a variable whose type is determined at runtime.
Definition: AnyMap.h:86
const string & asString() const
Return the held value, if it is a string.
Definition: AnyMap.cpp:739
bool empty() const
Return boolean indicating whether AnyValue is empty.
Definition: AnyMap.cpp:647
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:66
size_t lastPoint() const
The index of the last (that is, right-most) grid point belonging to this domain.
Definition: Domain1D.h:400
size_t domainIndex()
The left-to-right location of this domain.
Definition: Domain1D.h:52
shared_ptr< Solution > m_solution
Composite thermo/kinetics/transport handler.
Definition: Domain1D.h:567
size_t nComponents() const
Number of components at each grid point.
Definition: Domain1D.h:145
virtual void setMeta(const AnyMap &meta)
Retrieve meta data.
Definition: Domain1D.cpp:155
size_t nPoints() const
Number of grid points in this domain.
Definition: Domain1D.h:167
shared_ptr< Solution > solution() const
Return thermo/kinetics/transport manager used in the domain.
Definition: Domain1D.h:366
string m_id
Identity tag for the domain.
Definition: Domain1D.h:560
double prevSoln(size_t n, size_t j) const
Value of component n at point j in the previous solution.
Definition: Domain1D.h:441
size_t firstPoint() const
The index of the first (that is, left-most) grid point belonging to this domain.
Definition: Domain1D.h:392
void needJacUpdate()
Set this if something has changed in the governing equations (for example, the value of a constant ha...
Definition: Domain1D.cpp:95
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:384
virtual AnyMap getMeta() const
Retrieve meta data.
Definition: Domain1D.cpp:103
shared_ptr< SolutionArray > asArray(const double *soln) const override
Save the state of this domain as a SolutionArray.
Definition: Boundary1D.cpp:287
void eval(size_t jg, double *xg, double *rg, integer *diagg, double rdt) override
Evaluate the residual function at point j.
Definition: Boundary1D.cpp:282
void init() override
Initialize.
Definition: Boundary1D.cpp:277
void setMoleFractions(const string &xin) override
Set the mole fractions by specifying a string.
Definition: Boundary1D.cpp:122
shared_ptr< SolutionArray > asArray(const double *soln) const override
Save the state of this domain as a SolutionArray.
Definition: Boundary1D.cpp:241
void eval(size_t jg, double *xg, double *rg, integer *diagg, double rdt) override
Evaluate the residual function at point j.
Definition: Boundary1D.cpp:173
void fromArray(SolutionArray &arr, double *soln) override
Restore the solution for this domain from a SolutionArray.
Definition: Boundary1D.cpp:258
void init() override
Initialize.
Definition: Boundary1D.cpp:141
void setSpreadRate(double V0) override
set spreading rate
Definition: Boundary1D.cpp:99
void show(const double *x) override
Print the solution.
Definition: Boundary1D.cpp:106
size_t nPhases() const
The number of phases participating in the reaction mechanism.
Definition: Kinetics.h:184
size_t kineticsSpeciesIndex(size_t k, size_t n) const
The location of species k of phase n in species arrays.
Definition: Kinetics.h:276
size_t nTotalSpecies() const
The total number of species in all phases participating in the kinetics mechanism.
Definition: Kinetics.h:254
virtual void getNetProductionRates(double *wdot)
Species net production rates [kmol/m^3/s or kmol/m^2/s].
Definition: Kinetics.cpp:363
ThermoPhase & thermo(size_t n=0)
This method returns a reference to the nth ThermoPhase object defined in this kinetics mechanism.
Definition: Kinetics.h:242
shared_ptr< SolutionArray > asArray(const double *soln) const override
Save the state of this domain as a SolutionArray.
Definition: Boundary1D.cpp:406
void eval(size_t jg, double *xg, double *rg, integer *diagg, double rdt) override
Evaluate the residual function at point j.
Definition: Boundary1D.cpp:373
void init() override
Initialize.
Definition: Boundary1D.cpp:358
void setMoleFractions(const string &xin) override
Set the mole fractions by specifying a string.
Definition: Boundary1D.cpp:414
shared_ptr< SolutionArray > asArray(const double *soln) const override
Save the state of this domain as a SolutionArray.
Definition: Boundary1D.cpp:488
void eval(size_t jg, double *xg, double *rg, integer *diagg, double rdt) override
Evaluate the residual function at point j.
Definition: Boundary1D.cpp:456
void fromArray(SolutionArray &arr, double *soln) override
Restore the solution for this domain from a SolutionArray.
Definition: Boundary1D.cpp:505
void init() override
Initialize.
Definition: Boundary1D.cpp:433
virtual void setMoleFractions(const double *const x)
Set the mole fractions to the specified values.
Definition: Phase.cpp:289
size_t nSpecies() const
Returns the number of species in the phase.
Definition: Phase.h:231
void saveState(vector< double > &state) const
Save the current internal state of the phase.
Definition: Phase.cpp:236
string speciesName(size_t k) const
Name of the species with index k.
Definition: Phase.cpp:142
virtual size_t stateSize() const
Return size of vector defining internal state of the phase.
Definition: Phase.cpp:228
void setMoleFractionsByName(const Composition &xMap)
Set the species mole fractions by name.
Definition: Phase.cpp:330
const vector< double > & molecularWeights() const
Return a const reference to the internal vector of molecular weights.
Definition: Phase.cpp:395
virtual void setTemperature(double temp)
Set the internally stored temperature of the phase (K).
Definition: Phase.h:623
void getMassFractions(double *const y) const
Get the species mass fractions.
Definition: Phase.cpp:471
virtual double pressure() const
Return the thermodynamic pressure (Pa).
Definition: Phase.h:580
string name() const
Return the name of the phase.
Definition: Phase.cpp:20
void setKinetics(shared_ptr< Kinetics > kin) override
Set the kinetics manager.
Definition: Boundary1D.cpp:602
void resetBadValues(double *xg) override
When called, this function should reset "bad" values in the state vector such as negative species con...
Definition: Boundary1D.cpp:637
shared_ptr< SolutionArray > asArray(const double *soln) const override
Save the state of this domain as a SolutionArray.
Definition: Boundary1D.cpp:726
void eval(size_t jg, double *xg, double *rg, integer *diagg, double rdt) override
Evaluate the residual function at point j.
Definition: Boundary1D.cpp:643
void fromArray(SolutionArray &arr, double *soln) override
Restore the solution for this domain from a SolutionArray.
Definition: Boundary1D.cpp:745
string componentName(size_t n) const override
Name of the nth component. May be overloaded.
Definition: Boundary1D.cpp:614
void init() override
Initialize.
Definition: Boundary1D.cpp:623
void show(const double *x) override
Print the solution.
Definition: Boundary1D.cpp:758
A container class holding arrays of state information.
Definition: SolutionArray.h:33
void setLoc(int loc, bool restore=true)
Update the buffered location used to access SolutionArray entries.
AnyMap getAuxiliary(int loc)
Retrieve auxiliary data for a given location.
static shared_ptr< SolutionArray > create(const shared_ptr< Solution > &sol, int size=0, const AnyMap &meta={})
Instantiate a new SolutionArray reference.
Definition: SolutionArray.h:51
AnyMap & meta()
SolutionArray meta data.
shared_ptr< ThermoPhase > thermo()
Retrieve associated ThermoPhase object.
static shared_ptr< Solution > create()
Create an empty Solution object.
Definition: Solution.h:54
size_t rightExcessSpecies() const
Index of the species on the right boundary with the largest mass fraction.
Definition: StFlow.h:311
void setGas(const double *x, size_t j)
Set the gas object state to be consistent with the solution at point j.
Definition: StFlow.cpp:229
size_t leftExcessSpecies() const
Index of the species on the left boundary with the largest mass fraction.
Definition: StFlow.h:306
bool isFree() const
Retrieve flag indicating whether flow is freely propagating.
Definition: StFlow.h:263
bool isStrained() const
Retrieve flag indicating whether flow uses radial momentum.
Definition: StFlow.h:274
double T_fixed(size_t j) const
The fixed temperature value at point j.
Definition: StFlow.h:143
shared_ptr< SolutionArray > asArray(const double *soln) const override
Save the state of this domain as a SolutionArray.
Definition: Boundary1D.cpp:547
void eval(size_t jg, double *xg, double *rg, integer *diagg, double rdt) override
Evaluate the residual function at point j.
Definition: Boundary1D.cpp:522
void fromArray(SolutionArray &arr, double *soln) override
Restore the solution for this domain from a SolutionArray.
Definition: Boundary1D.cpp:554
void init() override
Initialize.
Definition: Boundary1D.cpp:517
void show(std::ostream &s, const double *x) override
Print the solution.
Definition: Boundary1D.cpp:562
double pressure() const override
Return the thermodynamic pressure (Pa).
Definition: SurfPhase.h:238
double size(size_t k) const
Returns the number of sites occupied by one molecule of species k.
Definition: SurfPhase.h:221
void setCoverages(const double *theta)
Set the surface site fractions to a specified state.
Definition: SurfPhase.cpp:215
double siteDensity() const
Returns the site density.
Definition: SurfPhase.h:216
void setCoveragesNoNorm(const double *theta)
Set the surface site fractions to a specified state.
Definition: SurfPhase.cpp:231
void getCoverages(double *theta) const
Return a vector of surface coverages.
Definition: SurfPhase.cpp:249
shared_ptr< SolutionArray > asArray(const double *soln) const override
Save the state of this domain as a SolutionArray.
Definition: Boundary1D.cpp:339
void eval(size_t jg, double *xg, double *rg, integer *diagg, double rdt) override
Evaluate the residual function at point j.
Definition: Boundary1D.cpp:300
void init() override
Initialize.
Definition: Boundary1D.cpp:295
Base class for a phase with thermodynamic properties.
Definition: ThermoPhase.h:390
virtual void setState_TP(double t, double p)
Set the temperature (K) and pressure (Pa)
const AnyMap & input() const
Access input data associated with the phase description.
void writelog(const string &fmt, const Args &... args)
Write a formatted message to the screen.
Definition: global.h:175
Namespace for the Cantera kernel.
Definition: AnyMap.cpp:564
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:180
@ c_offset_U
axial velocity
Definition: StFlow.h:25
@ c_offset_L
(1/r)dP/dr
Definition: StFlow.h:28
@ c_offset_V
strain rate
Definition: StFlow.h:26
@ c_offset_Y
mass fractions
Definition: StFlow.h:30
@ c_offset_T
temperature
Definition: StFlow.h:27