Cantera  4.0.0a1
Loading...
Searching...
No Matches
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
10
11using namespace std;
12
13namespace Cantera
14{
15
17{
18}
19
20void 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) {
36 if (!r.isConnector()) { // multi-point domain
38 if (m_left_nv > c_offset_Y) {
40 } else {
41 m_left_nsp = 0;
42 }
43 m_flow_left = dynamic_cast<Flow1D*>(&r);
44 if (m_flow_left != nullptr) {
46 }
47 } else {
48 throw CanteraError("Boundary1D::_init",
49 "Boundary domains can only be connected on the left to flow "
50 "domains, not '{}' domains.", r.domainType());
51 }
52 }
53
54 // if this is not the last domain, see what is connected on the right
55 if (m_index + 1 < container().nDomains()) {
57 if (!r.isConnector()) { // multi-point domain
59 if (m_right_nv > c_offset_Y) {
61 } else {
62 m_right_nsp = 0;
63 }
64 m_flow_right = dynamic_cast<Flow1D*>(&r);
65 if (m_flow_right != nullptr) {
66 m_phase_right = &m_flow_right->phase();
67 }
68 } else {
69 throw CanteraError("Boundary1D::_init",
70 "Boundary domains can only be connected on the right to flow "
71 "domains, not '{}' domains.", r.domainType());
72 }
73 }
74}
75
76void Boundary1D::fromArray(const shared_ptr<SolutionArray>& arr)
77{
78 setMeta(arr->meta());
79}
80
81// ---------------- Inlet1D methods ----------------
82
84{
85}
86
87Inlet1D::Inlet1D(shared_ptr<Solution> phase, const string& id)
88 : Inlet1D()
89{
91 m_solution->thermo()->addSpeciesLock();
92 m_id = id;
93 auto thermo = phase->thermo();
94 m_temp = thermo->temperature();
95 m_press = thermo->pressure();
96 m_nsp = thermo->nSpecies();
97 m_yin.resize(m_nsp);
98 thermo->getMassFractions(m_yin);
99}
100
101//! set spreading rate
103{
104 m_V0 = V0;
106}
107
109{
111 // Adjust flow domain temperature bounds based on inlet temperature
112 if (m_flow != nullptr && m_flow->lowerBound(c_offset_T) >= m_temp) {
114 }
115}
116
117void Inlet1D::show(span<const double> x)
118{
119 writelog(" Mass Flux: {:10.4g} kg/m^2/s \n", m_mdot);
120 writelog(" Temperature: {:10.4g} K \n", m_temp);
121 if (m_flow) {
122 writelog(" Mass Fractions: \n");
123 for (size_t k = 0; k < m_flow->phase().nSpecies(); k++) {
124 if (m_yin[k] != 0.0) {
125 writelog(" {:>16s} {:10.4g} \n",
126 m_flow->phase().speciesName(k), m_yin[k]);
127 }
128 }
129 }
130 writelog("\n");
131}
132
133void Inlet1D::setMoleFractions(const string& xin)
134{
135 if (m_solution) {
136 auto thermo = m_solution->thermo();
137 thermo->setMoleFractionsByName(xin);
138 thermo->getMassFractions(m_yin);
140 } else {
141 m_xstr = xin;
142 }
143}
144
145void Inlet1D::setMoleFractions(span<const double> xin)
146{
147 if (m_solution) {
148 auto thermo = m_solution->thermo();
149 thermo->setMoleFractions(xin);
150 thermo->getMassFractions(m_yin);
152 }
153}
154
155void Inlet1D::updateState(size_t loc)
156{
157 if (m_flow) {
159 }
160 m_solution->thermo()->setState_TPY(m_temp, m_press, m_yin);
161}
162
164{
165 _init(0);
166
167 // if a flow domain is present on the left, then this must be a right inlet.
168 // Note that an inlet object can only be a terminal object - it cannot have
169 // flows on both the left and right
170 if (m_flow_left && !m_flow_right) {
171 if (!m_flow_left->isStrained()) {
172 throw CanteraError("Inlet1D::init",
173 "Right inlets with right-to-left flow are only supported for "
174 "strained flow configurations.");
175 }
178 } else if (m_flow_right) {
180 m_flow = m_flow_right;
181 } else {
182 throw CanteraError("Inlet1D::init", "Inlet1D is not properly connected.");
183 }
185
186 // components = u, V, T, Lambda, + mass fractions
187 if (!m_nsp) {
188 m_nsp = m_flow->phase().nSpecies();
189 m_yin.resize(m_nsp, 0.0);
190 m_yin[0] = 1.0;
191 }
192 if (m_temp > 0) {
194 }
195 if (m_xstr != "") {
197 }
198}
199
200void Inlet1D::eval(size_t jg, span<const double> xg, span<double> rg,
201 span<int> diagg, double rdt)
202{
203 if (jg != npos && (jg + 2 < firstPoint() || jg > lastPoint() + 2)) {
204 return;
205 }
206
207 if (m_ilr == LeftInlet) {
208 // Array elements corresponding to the first point of the flow domain
209 span<const double> xb = xg.subspan(m_flow->loc());
210 span<double> rb = rg.subspan(m_flow->loc());
211
212 // The first flow residual is for u. This, however, is not modified by
213 // the inlet, since this is set within the flow domain from the
214 // continuity equation.
215
216 if (m_flow->doEnergy(0)) {
217 // The third flow residual is for T, where it is set to T(0). Subtract
218 // the local temperature to hold the flow T to the inlet T.
219 rb[c_offset_T] -= m_temp;
220 } else {
221 rb[c_offset_T] -= m_flow->T_fixed(0);
222 }
223
224 if (m_flow->isFree()) {
225 // if the flow is a freely-propagating flame, mdot is not specified.
226 // Set mdot equal to rho*u.
227 m_mdot = m_flow->density(0) * xb[c_offset_U];
228 } else if (m_flow->isStrained()) { // axisymmetric flow
230 // When using two-point control, the mass flow rate at the left inlet is
231 // not specified. Instead, the mass flow rate is dictated by the
232 // velocity at the left inlet, which comes from the U variable. The
233 // default boundary condition specified in the Flow1D.cpp file already
234 // handles this case. We only need to update the stored value of m_mdot
235 // so that other equations that use the quantity are consistent.
237 } else {
238 // The flow domain sets this to -rho*u. Add mdot to specify the mass
239 // flow rate
240 rb[c_offset_L] += m_mdot;
241 }
242
243 // spreading rate. The flow domain sets this to V(0),
244 // so for finite spreading rate subtract m_V0.
245 rb[c_offset_V] -= m_V0;
246 } else { // unstrained flow
247 rb[c_offset_U] = m_flow->density(0) * xb[c_offset_U] - m_mdot;
248 }
249
250 // add the convective term to the species residual equations
251 for (size_t k = 0; k < m_nsp; k++) {
252 if (k != m_flow_right->leftExcessSpecies()) {
253 rb[c_offset_Y+k] += m_mdot*m_yin[k];
254 }
255 }
256
257 } else {
258 // right inlet (should only be used for counter-flow flames)
259 // Array elements corresponding to the last point in the flow domain
260 span<double> rb = rg.subspan(loc() - m_flow->nComponents());
261 span<const double> xb = xg.subspan(loc() - m_flow->nComponents());
262 size_t last_index = m_flow->nPoints() - 1;
263
264 rb[c_offset_V] -= m_V0;
265 if (m_flow->doEnergy(m_flow->nPoints() - 1)) {
266 rb[c_offset_T] -= m_temp; // T
267 } else {
268 rb[c_offset_T] -= m_flow->T_fixed(m_flow->nPoints() - 1);
269 }
270
271 if (m_flow->twoPointControlEnabled()) { // For point control adjustments
272 // At the right boundary, the mdot is dictated by the velocity at the right
273 // boundary, which comes from the Uo variable. The variable Uo is the
274 // left-moving velocity and has a negative value, so the mass flow has to be
275 // negated to give a positive value when using Uo.
276 m_mdot = -m_flow->density(last_index) * xb[c_offset_Uo];
277 }
278 rb[c_offset_U] += m_mdot;
279
280 for (size_t k = 0; k < m_nsp; k++) {
281 if (k != m_flow_left->rightExcessSpecies()) {
282 rb[c_offset_Y+k] += m_mdot * m_yin[k];
283 }
284 }
285 }
286}
287
288shared_ptr<SolutionArray> Inlet1D::toArray(bool normalize)
289{
291 meta["mass-flux"] = m_mdot;
292 auto arr = SolutionArray::create(m_solution, 1, meta);
293
294 // set gas state (using pressure from adjacent domain)
295 double pressure = m_flow->phase().pressure();
296 auto thermo = m_solution->thermo();
297 thermo->setState_TPY(m_temp, pressure, m_yin);
298 vector<double> data(thermo->stateSize());
299 thermo->saveState(data);
300
301 arr->setState(0, data);
302 if (normalize) {
303 arr->normalize();
304 }
305 return arr;
306}
307
308void Inlet1D::fromArray(const shared_ptr<SolutionArray>& arr)
309{
310 Boundary1D::setMeta(arr->meta());
311 arr->setLoc(0);
312 auto thermo = arr->thermo();
313 auto meta = arr->meta();
314 m_temp = thermo->temperature();
315 if (meta.hasKey("mass-flux")) {
316 m_mdot = meta.at("mass-flux").asDouble();
317 } else {
318 // convert data format used by Python h5py export (Cantera < 3.0)
319 auto aux = arr->getAuxiliary(0);
320 m_mdot = thermo->density() * aux.at("velocity").as<double>();
321 }
322 thermo->getMassFractions(m_yin);
323}
324
325// ------------- Empty1D -------------
326
328{
329 _init(0);
330}
331
332void Empty1D::eval(size_t jg, span<const double> xg, span<double> rg,
333 span<int> diagg, double rdt)
334{
335}
336
337shared_ptr<SolutionArray> Empty1D::toArray(bool normalize)
338{
340 return SolutionArray::create(m_solution, 0, meta);
341}
342
343// -------------- Symm1D --------------
344
346{
347 _init(0);
348}
349
350void Symm1D::eval(size_t jg, span<const double> xg, span<double> rg,
351 span<int> diagg, double rdt)
352{
353 if (jg != npos && (jg + 2< firstPoint() || jg > lastPoint() + 2)) {
354 return;
355 }
356
357 if (m_flow_right) {
358 size_t nc = m_flow_right->nComponents();
359 span<const double> xb = xg.subspan(loc(), nc);
360 span<double> rb = rg.subspan(loc(), nc);
361 span<int> db = diagg.subspan(loc(), nc);
362 db[c_offset_V] = 0;
363 db[c_offset_T] = 0;
364 rb[c_offset_V] = xb[c_offset_V] - xb[c_offset_V + nc]; // zero dV/dz
365 if (m_flow_right->doEnergy(0)) {
366 rb[c_offset_T] = xb[c_offset_T] - xb[c_offset_T + nc]; // zero dT/dz
367 }
368 }
369
370 if (m_flow_left) {
371 size_t nc = m_flow_left->nComponents();
372 span<const double> xb = xg.subspan(loc() - nc, nc);
373 span<const double> xb2 = xg.subspan(loc() - 2*nc, nc); // second point from the left
374 span<double> rb = rg.subspan(loc() - nc, nc);
375 span<int> db = diagg.subspan(loc() - nc, nc);
376 db[c_offset_V] = 0;
377 db[c_offset_T] = 0;
378 rb[c_offset_V] = xb[c_offset_V] - xb2[c_offset_V]; // zero dV/dz
380 rb[c_offset_T] = xb[c_offset_T] - xb2[c_offset_T]; // zero dT/dz
381 }
382 }
383}
384
385shared_ptr<SolutionArray> Symm1D::toArray(bool normalize)
386{
388 return SolutionArray::create(m_solution, 0, meta);
389}
390
391// -------- Outlet1D --------
392
394{
395}
396
397OutletRes1D::OutletRes1D(shared_ptr<Solution> phase, const string& id)
398 : OutletRes1D()
399{
401 m_solution->thermo()->addSpeciesLock();
402 m_id = id;
403}
404
406{
407 _init(0);
408
409 if (m_flow_right) {
410 throw CanteraError("Outlet1D::init",
411 "Left outlets with right-to-left flow are not supported.");
412 }
413 if (m_flow_left) {
415 } else {
416 throw CanteraError("Outlet1D::init", "Outlet1D is not connected.");
417 }
418}
419
420void Outlet1D::eval(size_t jg, span<const double> xg, span<double> rg,
421 span<int> diagg, double rdt)
422{
423 if (jg != npos && (jg + 2 < firstPoint() || jg > lastPoint() + 2)) {
424 return;
425 }
426
427 // flow is left-to-right; access values for the points to the left
428 size_t nc = m_flow_left->nComponents();
429 span<const double> xb = xg.subspan(loc() - nc, nc); // last point
430 span<const double> xb2 = xg.subspan(loc() - 2*nc, nc); // second-to-last point
431 span<double> rb = rg.subspan(loc() - nc, nc);
432 span<int> db = diagg.subspan(loc() - nc, nc);
433
434 size_t last = m_flow_left->nPoints() - 1;
435 if (m_flow_left->doEnergy(last)) {
436 rb[c_offset_T] = xb[c_offset_T] - xb2[c_offset_T]; // zero T gradient
437 } else {
438 rb[c_offset_T] = xb[c_offset_T] - m_flow_left->T_fixed(last);
439 }
440 size_t kSkip = c_offset_Y + m_flow_left->rightExcessSpecies();
441 for (size_t k = c_offset_Y; k < nc; k++) {
442 if (k != kSkip) {
443 rb[k] = xb[k] - xb2[k]; // zero mass fraction gradient
444 db[k] = 0;
445 }
446 }
447}
448
449shared_ptr<SolutionArray> Outlet1D::toArray(bool normalize)
450{
452 return SolutionArray::create(m_solution, 0, meta);
453}
454
455// -------- OutletRes1D --------
456
457void OutletRes1D::setMoleFractions(const string& xres)
458{
459 m_xstr = xres;
460 if (m_flow) {
464 }
465}
466
467void OutletRes1D::setMoleFractions(span<const double> xres)
468{
469 if (m_flow) {
473 }
474}
475
477{
478 _init(0);
479
480 if (m_flow_right) {
481 throw CanteraError("OutletRes1D::init",
482 "Left outlets with right-to-left flow are not supported.");
483 }
484 if (m_flow_left) {
486 } else {
487 throw CanteraError("OutletRes1D::init", "no flow!");
488 }
489
490 m_nsp = m_flow->phase().nSpecies();
491 m_yres.resize(m_nsp, 0.0);
492 if (m_xstr != "") {
494 } else {
495 m_yres[0] = 1.0;
496 }
497}
498
499void OutletRes1D::eval(size_t jg, span<const double> xg, span<double> rg,
500 span<int> diagg, double rdt)
501{
502 if (jg != npos && (jg + 2 < firstPoint() || jg > lastPoint() + 2)) {
503 return;
504 }
505
506 // flow is left-to-right; access values for the point to the left
507 size_t nc = m_flow_left->nComponents();
508 span<const double> xb = xg.subspan(loc() - nc, nc);
509 span<const double> xb2 = xg.subspan(loc() - 2*nc, nc); // second point from the left
510 span<double> rb = rg.subspan(loc() - nc, nc);
511 span<int> db = diagg.subspan(loc() - nc, nc);
512
513 size_t last = m_flow_left->nPoints() - 1;
514 if (m_flow_left->doEnergy(last)) {
515 rb[c_offset_T] = xb[c_offset_T] - xb2[c_offset_T]; // zero T gradient
516 } else {
517 rb[c_offset_T] = xb[c_offset_T] - m_flow_left->T_fixed(last);
518 }
519 size_t kSkip = m_flow_left->rightExcessSpecies();
520 for (size_t k = c_offset_Y; k < nc; k++) {
521 if (k != kSkip) {
522 rb[k] = xb[k] - m_yres[k-c_offset_Y]; // fixed Y
523 db[k] = 0;
524 }
525 }
526}
527
528shared_ptr<SolutionArray> OutletRes1D::toArray(bool normalize)
529{
531 meta["temperature"] = m_temp;
532 auto arr = SolutionArray::create(m_solution, 1, meta);
533
534 // set gas state (using pressure from adjacent domain)
535 double pressure = m_flow->phase().pressure();
536 auto thermo = m_solution->thermo();
537 thermo->setState_TPY(m_temp, pressure, m_yres);
538 vector<double> data(thermo->stateSize());
539 thermo->saveState(data);
540
541 arr->setState(0, data);
542 if (normalize) {
543 arr->normalize();
544 }
545 return arr;
546}
547
548void OutletRes1D::fromArray(const shared_ptr<SolutionArray>& arr)
549{
550 Boundary1D::setMeta(arr->meta());
551 arr->setLoc(0);
552 auto thermo = arr->thermo();
553 m_temp = thermo->temperature();
554 auto Y = thermo->massFractions();
555 m_yres.assign(Y.begin(), Y.end());
556}
557
558// -------- Surf1D --------
559
561{
562 _init(0);
563}
564
565void Surf1D::eval(size_t jg, span<const double> xg, span<double> rg,
566 span<int> diagg, double rdt)
567{
568 if (jg != npos && (jg + 2 < firstPoint() || jg > lastPoint() + 2)) {
569 return;
570 }
571
572 if (m_flow_right) {
573 span<double> rb = rg.subspan(loc(), m_flow_right->nComponents());
574 span<const double> xb = xg.subspan(loc(), m_flow_right->nComponents());
575 rb[c_offset_T] = xb[c_offset_T] - m_temp; // specified T
576 }
577
578 if (m_flow_left) {
579 size_t nc = m_flow_left->nComponents();
580 span<double> rb = rg.subspan(loc() - nc, nc);
581 span<const double> xb = xg.subspan(loc() - nc, nc);
582 rb[c_offset_T] = xb[c_offset_T] - m_temp; // specified T
583 }
584}
585
586shared_ptr<SolutionArray> Surf1D::toArray(bool normalize)
587{
589 meta["temperature"] = m_temp;
590 return SolutionArray::create(m_solution, 0, meta);
591}
592
593void Surf1D::fromArray(const shared_ptr<SolutionArray>& arr)
594{
595 auto meta = arr->meta();
596 m_temp = meta["temperature"].asDouble();
597 meta.erase("temperature");
599}
600
601void Surf1D::show(span<const double> x)
602{
603 writelog(" Temperature: {:10.4g} K \n\n", m_temp);
604}
605
606// -------- ReactingSurf1D --------
607
609 : m_kin(0)
610 , m_nsp(0)
611{
612}
613
614ReactingSurf1D::ReactingSurf1D(shared_ptr<Solution> phase, const string& id)
615{
616 auto thermo = std::dynamic_pointer_cast<SurfPhase>(phase->thermo());
617 if (!thermo) {
618 throw CanteraError("ReactingSurf1D::ReactingSurf1D",
619 "Detected incompatible ThermoPhase type '{}'", phase->thermo()->type());
620 }
621 auto kin = std::dynamic_pointer_cast<InterfaceKinetics>(phase->kinetics());
622 if (!kin) {
623 throw CanteraError("ReactingSurf1D::ReactingSurf1D",
624 "Detected incompatible kinetics type '{}'",
625 phase->kinetics()->kineticsType());
626 }
628 m_solution->thermo()->addSpeciesLock();
629 m_id = id;
630 m_kin = kin.get();
631 m_sphase = thermo.get();
633 m_enabled = true;
634}
635
636string ReactingSurf1D::componentName(size_t n) const
637{
638 if (n < m_nsp) {
639 return m_sphase->speciesName(n);
640 }
641 throw IndexError("ReactingSurf1D::componentName", "component", n, m_nsp);
642}
643
644size_t ReactingSurf1D::componentIndex(const string& name, bool checkAlias) const
645{
646 return m_sphase->speciesIndex(name, true);
647}
648
650{
651 m_nv = m_nsp;
652 _init(m_nsp);
653
654 m_fixed_cov.resize(m_nsp, 0.0);
655 m_fixed_cov[0] = 1.0;
656 m_work.resize(m_kin->nTotalSpecies(), 0.0);
657
658 for (size_t n = 0; n < m_nsp; n++) {
659 setBounds(n, -1.0e-5, 2.0);
660 }
661}
662
663void ReactingSurf1D::resetBadValues(span<double> xg) {
664 span<double> x = xg.subspan(loc(), m_nsp);
667}
668
669void ReactingSurf1D::eval(size_t jg, span<const double> xg, span<double> rg,
670 span<int> diagg, double rdt)
671{
672 if (jg != npos && (jg + 2 < firstPoint() || jg > lastPoint() + 2)) {
673 return;
674 }
675
676 // start of local part of global arrays
677 span<const double> x = xg.subspan(loc(), m_nsp);
678 span<double> r = rg.subspan(loc(), m_nsp);
679 span<int> diag = diagg.subspan(loc(), m_nsp);
680
681 // set the coverages
682 double sum = 0.0;
683 for (size_t k = 0; k < m_nsp; k++) {
684 m_work[k] = x[k];
685 sum += x[k];
686 }
689
690 // set the left gas state to the adjacent point
691
692 size_t leftloc = 0, rightloc = 0;
693 size_t pnt = 0;
694
695 if (m_flow_left) {
696 leftloc = m_flow_left->loc();
697 pnt = m_flow_left->nPoints() - 1;
698 m_flow_left->setGas(xg.subspan(leftloc, m_flow_left->size()), pnt);
699 }
700
701 if (m_flow_right) {
702 rightloc = m_flow_right->loc();
703 m_flow_right->setGas(xg.subspan(rightloc, m_flow_right->size()), 0);
704 }
705
707 double rs0 = 1.0/m_sphase->siteDensity();
708
709 if (m_enabled) {
710 for (size_t k = 0; k < m_nsp; k++) {
711 r[k] = m_work[k] * m_sphase->size(k) * rs0;
712 r[k] -= rdt*(x[k] - prevSoln(k,0));
713 diag[k] = 1;
714 }
715 r[0] = 1.0 - sum;
716 diag[0] = 0;
717 } else {
718 for (size_t k = 0; k < m_nsp; k++) {
719 r[k] = x[k] - m_fixed_cov[k];
720 diag[k] = 0;
721 }
722 }
723
724 if (m_flow_right) {
725 span<double> rb = r.subspan(m_nsp, m_flow_right->nComponents());
726 span<const double> xb = x.subspan(m_nsp, m_flow_right->nComponents());
727 rb[c_offset_T] = xb[c_offset_T] - m_temp; // specified T
728 }
729 if (m_flow_left) {
730 size_t nc = m_flow_left->nComponents();
731 auto mwleft = m_phase_left->molecularWeights();
732 span<double> rb = rg.subspan(loc() - nc, nc);
733 span<const double> xb = xg.subspan(loc() - nc, nc);
734 rb[c_offset_T] = xb[c_offset_T] - m_temp; // specified T
735 size_t nSkip = m_flow_left->rightExcessSpecies();
736 size_t l_offset = 0;
737 ThermoPhase* left_thermo = &m_flow_left->phase();
738 for (size_t nth = 0; nth < m_kin->nPhases(); nth++) {
739 if (&m_kin->thermo(nth) == left_thermo) {
740 l_offset = m_kin->kineticsSpeciesIndex(0, nth);
741 break;
742 }
743 }
744 for (size_t nl = 0; nl < m_left_nsp; nl++) {
745 if (nl != nSkip) {
746 rb[c_offset_Y+nl] += m_work[nl + l_offset]*mwleft[nl];
747 }
748 }
749 }
750}
751
752double ReactingSurf1D::value(const string& component) const
753{
754 if (!m_state) {
755 throw CanteraError("ReactingSurf1D::value",
756 "Domain needs to be installed in a container.");
757 }
758 auto i = componentIndex(component);
759 const double* soln = m_state->data() + m_iloc;
760 return soln[index(i, 0)];
761}
762
763shared_ptr<SolutionArray> ReactingSurf1D::toArray(bool normalize)
764{
765 if (!m_state) {
766 throw CanteraError("ReactingSurf1D::toArray",
767 "Domain needs to be installed in a container before calling toArray.");
768 }
769 double* soln = m_state->data() + m_iloc;
771 meta["temperature"] = m_temp;
772 meta["phase"]["name"] = m_sphase->name();
773 AnyValue source = m_sphase->input().getMetadata("filename");
774 meta["phase"]["source"] = source.empty() ? "<unknown>" : source.asString();
775
776 // set state of surface phase
778 m_sphase->setCoverages(span<const double>(soln, m_nsp));
779 vector<double> data(m_sphase->stateSize());
780 m_sphase->saveState(data);
781
782 auto arr = SolutionArray::create(m_solution, 1, meta);
783 arr->setState(0, data);
784 if (normalize) {
785 arr->normalize();
786 }
787 return arr;
788}
789
790void ReactingSurf1D::fromArray(const shared_ptr<SolutionArray>& arr)
791{
792 if (!m_state) {
793 throw CanteraError("Domain1D::fromArray",
794 "Domain needs to be installed in a container before calling fromArray.");
795 }
796 resize(nComponents(), arr->size());
798 span<double> soln(m_state->data() + m_iloc, m_nsp);
799
800 Boundary1D::setMeta(arr->meta());
801 arr->setLoc(0);
802 auto surf = std::dynamic_pointer_cast<SurfPhase>(arr->thermo());
803 if (!surf) {
804 throw CanteraError("ReactingSurf1D::fromArray",
805 "Restoring of coverages requires surface phase");
806 }
807 m_temp = surf->temperature();
808 surf->getCoverages(soln);
809 _finalize(soln);
810}
811
812void ReactingSurf1D::show(span<const double> x)
813{
814 writelog(" Temperature: {:10.4g} K \n", m_temp);
815 writelog(" Coverages: \n");
816 for (size_t k = 0; k < m_nsp; k++) {
817 writelog(" {:>20s} {:10.4g} \n", m_sphase->speciesName(k), x[k]);
818 }
819 writelog("\n");
820}
821}
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:623
A map of string keys to values whose type can vary at runtime.
Definition AnyMap.h:431
A wrapper for a variable whose type is determined at runtime.
Definition AnyMap.h:88
const string & asString() const
Return the held value, if it is a string.
Definition AnyMap.cpp:782
bool empty() const
Return boolean indicating whether AnyValue is empty.
Definition AnyMap.cpp:690
ThermoPhase * m_phase_left
Thermo object used by left flow domain.
Definition Boundary1D.h:125
double m_mdot
Mass flow rate at the boundary.
Definition Boundary1D.h:131
double m_temp
Temperature of the boundary.
Definition Boundary1D.h:129
void _init(size_t n)
Initialize member variables based on the adjacent domains.
Flow1D * m_flow_left
Flow domain to the left of this boundary.
Definition Boundary1D.h:119
ThermoPhase * m_phase_right
Thermo object used by right flow domain.
Definition Boundary1D.h:126
void fromArray(const shared_ptr< SolutionArray > &arr) override
Restore the solution for this domain from a SolutionArray.
size_t m_right_nsp
Number of species in right flow domain.
Definition Boundary1D.h:124
virtual void setTemperature(double t)
Set the temperature.
Definition Boundary1D.h:61
size_t m_left_nsp
Number of species in left flow domain.
Definition Boundary1D.h:123
Boundary1D()
Default constructor.
size_t m_right_nv
Number of state vector components in right flow domain.
Definition Boundary1D.h:122
size_t m_left_nv
Flow domain to the right of this boundary.
Definition Boundary1D.h:121
Base class for exceptions thrown by Cantera classes.
Base class for one-dimensional domains.
Definition Domain1D.h:29
size_t lastPoint() const
The index of the last (that is, right-most) grid point belonging to this domain.
Definition Domain1D.h:532
size_t m_iloc
Starting location within the solution vector for unknowns that correspond to this domain.
Definition Domain1D.h:696
shared_ptr< Solution > m_solution
Composite thermo/kinetics/transport handler.
Definition Domain1D.h:713
OneDim * m_container
Parent OneDim simulation containing this and adjacent domains.
Definition Domain1D.h:687
size_t nComponents() const
Number of components at each grid point.
Definition Domain1D.h:142
size_t size() const
Return the size of the solution vector (the product of m_nv and m_points).
Definition Domain1D.h:511
virtual bool isConnector()
True if the domain is a connector domain.
Definition Domain1D.h:54
virtual void setMeta(const AnyMap &meta)
Retrieve meta data.
Definition Domain1D.cpp:155
size_t m_index
Left-to-right location of this domain.
Definition Domain1D.h:689
string id() const
Returns the identifying tag for this domain.
Definition Domain1D.h:577
shared_ptr< Solution > phase() const
Return thermo/kinetics/transport manager used in the domain.
Definition Domain1D.h:506
size_t m_nv
Number of solution components.
Definition Domain1D.h:675
size_t nPoints() const
Number of grid points in this domain.
Definition Domain1D.h:147
virtual string domainType() const
Domain type flag.
Definition Domain1D.h:46
double lowerBound(size_t n) const
Lower bound on the nth component.
Definition Domain1D.h:251
shared_ptr< vector< double > > m_state
data pointer shared from OneDim
Definition Domain1D.h:672
virtual void resize(size_t nv, size_t np)
Resize the domain to have nv components and np grid points.
Definition Domain1D.cpp:36
double upperBound(size_t n) const
Upper bound on the nth component.
Definition Domain1D.h:246
double m_press
pressure [Pa]
Definition Domain1D.h:670
const OneDim & container() const
The container holding this domain.
Definition Domain1D.h:80
string m_id
Identity tag for the domain.
Definition Domain1D.h:706
void setBounds(size_t n, double lower, double upper)
Set the upper and lower bounds for a solution component, n.
Definition Domain1D.h:190
double prevSoln(size_t n, size_t j) const
Value of component n at point j in the previous solution.
Definition Domain1D.h:567
size_t firstPoint() const
The index of the first (that is, left-most) grid point belonging to this domain.
Definition Domain1D.h:527
void needJacUpdate()
Set this if something has changed in the governing equations (for example, the value of a constant ha...
Definition Domain1D.cpp:119
size_t index(size_t n, size_t j) const
Returns the index of the solution vector, which corresponds to component n at grid point j.
Definition Domain1D.h:332
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:522
virtual AnyMap getMeta() const
Retrieve meta data.
Definition Domain1D.cpp:127
shared_ptr< SolutionArray > toArray(bool normalize=false) override
Save the state of this domain to a SolutionArray.
void eval(size_t jg, span< const double > xg, span< double > rg, span< int > diagg, double rdt) override
Evaluate the residual function at point j.
void init() override
Initialize.
This class represents 1D flow domains that satisfy the one-dimensional similarity solution for chemic...
Definition Flow1D.h:47
double density(size_t j) const
Get the density [kg/m³] at point j
Definition Flow1D.h:376
bool doEnergy(size_t j)
true if the energy equation is solved at point j or false if a fixed temperature condition is imposed...
Definition Flow1D.h:361
ThermoPhase & phase()
Access the phase object used to compute thermodynamic properties for points in this domain.
Definition Flow1D.h:69
bool twoPointControlEnabled() const
Returns the status of the two-point control.
Definition Flow1D.h:354
size_t rightExcessSpecies() const
Index of the species on the right boundary with the largest mass fraction.
Definition Flow1D.h:435
double pressure() const
The current pressure [Pa].
Definition Flow1D.h:130
void setViscosityFlag(bool dovisc)
Specify if the viscosity term should be included in the momentum equation.
Definition Flow1D.h:402
size_t leftExcessSpecies() const
Index of the species on the left boundary with the largest mass fraction.
Definition Flow1D.h:430
bool isFree() const
Retrieve flag indicating whether flow is freely propagating.
Definition Flow1D.h:386
bool isStrained() const
Retrieve flag indicating whether flow uses radial momentum.
Definition Flow1D.h:397
void setGas(span< const double > x, size_t j)
Set the gas object state to be consistent with the solution at point j.
Definition Flow1D.cpp:233
double T_fixed(size_t j) const
The fixed temperature value at point j.
Definition Flow1D.h:162
An array index is out of range.
void setMoleFractions(const string &xin) override
Set the mole fractions by specifying a string.
vector< double > m_yin
inlet mass fractions
Definition Boundary1D.h:190
int m_ilr
A marker that indicates whether this is a left inlet or a right inlet.
Definition Boundary1D.h:184
shared_ptr< SolutionArray > toArray(bool normalize=false) override
Save the state of this domain to a SolutionArray.
string m_xstr
inlet mass fractions.
Definition Boundary1D.h:191
size_t nSpecies() override
Get the number of species.
Definition Boundary1D.h:165
void fromArray(const shared_ptr< SolutionArray > &arr) override
Restore the solution for this domain from a SolutionArray.
void updateState(size_t loc) override
Update state at given location to state of associated Solution object.
void setTemperature(double T) override
Set the temperature.
void eval(size_t jg, span< const double > xg, span< double > rg, span< int > diagg, double rdt) override
Evaluate the residual function at point j.
void show(span< const double > x) override
Print the solution.
size_t m_nsp
Number of species in the adjacent flow domain.
Definition Boundary1D.h:189
void init() override
Initialize.
Flow1D * m_flow
the adjacent flow domain
Definition Boundary1D.h:192
void setSpreadRate(double V0) override
set spreading rate
double m_V0
The spread rate of the inlet [1/s].
Definition Boundary1D.h:187
Inlet1D()
Default constructor.
ThermoPhase & thermo(size_t n=0)
This method returns a reference to the nth ThermoPhase object defined in this kinetics mechanism.
Definition Kinetics.h:239
size_t nPhases() const
The number of phases participating in the reaction mechanism.
Definition Kinetics.h:189
virtual void getNetProductionRates(span< double > wdot)
Species net production rates [kmol/m^3/s or kmol/m^2/s].
Definition Kinetics.cpp:447
size_t kineticsSpeciesIndex(size_t k, size_t n) const
The location of species k of phase n in species arrays.
Definition Kinetics.h:273
size_t nTotalSpecies() const
The total number of species in all phases participating in the kinetics mechanism.
Definition Kinetics.h:251
void resize() override
Call to set the size of internal data structures after first defining the system or if the problem si...
Definition OneDim.cpp:177
Domain1D & domain(size_t i) const
Return a reference to domain i.
Definition OneDim.h:65
shared_ptr< SolutionArray > toArray(bool normalize=false) override
Save the state of this domain to a SolutionArray.
void eval(size_t jg, span< const double > xg, span< double > rg, span< int > diagg, double rdt) override
Evaluate the residual function at point j.
void init() override
Initialize.
An outlet with specified composition.
Definition Boundary1D.h:298
void setMoleFractions(const string &xin) override
Set the mole fractions by specifying a string.
shared_ptr< SolutionArray > toArray(bool normalize=false) override
Save the state of this domain to a SolutionArray.
OutletRes1D()
Default constructor.
string m_xstr
Mole fractions in the reservoir.
Definition Boundary1D.h:333
vector< double > m_yres
Mass fractions in the reservoir.
Definition Boundary1D.h:332
void fromArray(const shared_ptr< SolutionArray > &arr) override
Restore the solution for this domain from a SolutionArray.
void eval(size_t jg, span< const double > xg, span< double > rg, span< int > diagg, double rdt) override
Evaluate the residual function at point j.
size_t m_nsp
Number of species in the adjacent flow domain.
Definition Boundary1D.h:331
void init() override
Initialize.
Flow1D * m_flow
The adjacent flow domain.
Definition Boundary1D.h:334
void getMassFractions(span< double > y) const
Get the species mass fractions.
Definition Phase.cpp:479
size_t nSpecies() const
Returns the number of species in the phase.
Definition Phase.h:246
size_t speciesIndex(const string &name, bool raise=true) const
Returns the index of a species named 'name' within the Phase object.
Definition Phase.cpp:127
span< const double > molecularWeights() const
Return a const reference to the internal vector of molecular weights.
Definition Phase.cpp:401
string speciesName(size_t k) const
Name of the species with index k.
Definition Phase.cpp:143
virtual size_t stateSize() const
Return size of vector defining internal state of the phase.
Definition Phase.cpp:249
void setMoleFractionsByName(const Composition &xMap)
Set the species mole fractions by name.
Definition Phase.cpp:326
virtual void setTemperature(double temp)
Set the internally stored temperature of the phase (K).
Definition Phase.h:646
virtual void setMoleFractions(span< const double > x)
Set the mole fractions to the specified values.
Definition Phase.cpp:283
virtual double pressure() const
Return the thermodynamic pressure (Pa).
Definition Phase.h:603
string name() const
Return the name of the phase.
Definition Phase.cpp:20
virtual void saveState(span< double > state) const
Write to array 'state' the current internal state.
Definition Phase.cpp:257
SurfPhase * m_sphase
phase representing the surface species
Definition Boundary1D.h:425
size_t componentIndex(const string &name, bool checkAlias=true) const override
Index of component with name name.
InterfaceKinetics * m_kin
surface kinetics mechanism
Definition Boundary1D.h:424
bool m_enabled
True if coverage equations are being solved.
Definition Boundary1D.h:427
vector< double > m_fixed_cov
Fixed values of the coverages used when coverage equations are not being solved.
Definition Boundary1D.h:435
ReactingSurf1D()
Default constructor.
vector< double > m_work
temporary vector used to store coverages and production rates.
Definition Boundary1D.h:431
shared_ptr< SolutionArray > toArray(bool normalize=false) override
Save the state of this domain to a SolutionArray.
double value(const string &component) const override
Set a single component value at a boundary.
void fromArray(const shared_ptr< SolutionArray > &arr) override
Restore the solution for this domain from a SolutionArray.
void eval(size_t jg, span< const double > xg, span< double > rg, span< int > diagg, double rdt) override
Evaluate the residual function at point j.
void show(span< const double > x) override
Print the solution.
size_t m_nsp
the number of surface phase species
Definition Boundary1D.h:426
void _finalize(span< const double > x) override
In some cases, a domain may need to set parameters that depend on the initial solution estimate.
Definition Boundary1D.h:417
void resetBadValues(span< double > xg) override
When called, this function should reset "bad" values in the state vector such as negative species con...
string componentName(size_t n) const override
Name of component n. May be overloaded.
void init() override
Initialize.
static shared_ptr< SolutionArray > create(const shared_ptr< Solution > &sol, int size=0, const AnyMap &meta={})
Instantiate a new SolutionArray reference.
shared_ptr< SolutionArray > toArray(bool normalize=false) override
Save the state of this domain to a SolutionArray.
void fromArray(const shared_ptr< SolutionArray > &arr) override
Restore the solution for this domain from a SolutionArray.
void eval(size_t jg, span< const double > xg, span< double > rg, span< int > diagg, double rdt) override
Evaluate the residual function at point j.
void show(span< const double > x) override
Print the solution.
void init() override
Initialize.
double pressure() const override
Return the thermodynamic pressure (Pa).
Definition SurfPhase.h:254
void setCoverages(span< const double > theta)
Set the surface site fractions to a specified state.
double size(size_t k) const
Returns the number of sites occupied by one molecule of species k.
Definition SurfPhase.h:237
double siteDensity() const
Returns the site density.
Definition SurfPhase.h:232
void setCoveragesNoNorm(span< const double > theta)
Set the surface site fractions to a specified state.
void getCoverages(span< double > theta) const
Return a vector of surface coverages.
shared_ptr< SolutionArray > toArray(bool normalize=false) override
Save the state of this domain to a SolutionArray.
void eval(size_t jg, span< const double > xg, span< double > rg, span< int > diagg, double rdt) override
Evaluate the residual function at point j.
void init() override
Initialize.
Base class for a phase with thermodynamic properties.
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:171
Namespace for the Cantera kernel.
Definition AnyMap.cpp:595
const size_t npos
index returned by functions to indicate "no position"
Definition ct_defs.h:183
const int LeftInlet
Unique identifier for the left inlet.
Definition Boundary1D.h:22
const int RightInlet
Unique identifier for the right inlet.
Definition Boundary1D.h:25
@ c_offset_U
axial velocity [m/s]
Definition Flow1D.h:26
@ c_offset_L
(1/r)dP/dr
Definition Flow1D.h:29
@ c_offset_V
strain rate
Definition Flow1D.h:27
@ c_offset_Y
mass fractions
Definition Flow1D.h:32
@ c_offset_Uo
oxidizer axial velocity [m/s]
Definition Flow1D.h:31
@ c_offset_T
temperature [kelvin]
Definition Flow1D.h:28