16 Boundary1D::Boundary1D() : Domain1D(1, 1, 0.0),
17 m_flow_left(0), m_flow_right(0),
18 m_ilr(0), m_left_nv(0), m_right_nv(0),
19 m_left_loc(0), m_right_loc(0),
21 m_left_nsp(0), m_right_nsp(0),
22 m_sp_left(0), m_sp_right(0),
23 m_start_left(0), m_start_right(0),
24 m_phase_left(0), m_phase_right(0), m_temp(0.0), m_mdot(0.0)
26 m_type = cConnectorType;
29 void Boundary1D::_init(
size_t n)
31 if (m_index ==
npos) {
32 throw CanteraError(
"Boundary1D::_init",
33 "install in container before calling init.");
44 Domain1D& r = container().domain(m_index-1);
45 if (!r.isConnector()) {
46 m_flow_left = (StFlow*)&r;
47 m_left_nv = m_flow_left->nComponents();
48 m_left_points = m_flow_left->nPoints();
49 m_left_loc = container().start(m_index-1);
50 m_left_nsp = m_left_nv - c_offset_Y;
51 m_phase_left = &m_flow_left->phase();
53 throw CanteraError(
"Boundary1D::_init",
54 "Boundary domains can only be connected on the left to flow "
55 "domains, not type {} domains.", r.domainType());
60 if (m_index + 1 < container().nDomains()) {
61 Domain1D& r = container().domain(m_index+1);
62 if (!r.isConnector()) {
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 - c_offset_Y;
67 m_phase_right = &m_flow_right->phase();
69 throw CanteraError(
"Boundary1D::_init",
70 "Boundary domains can only be connected on the right to flow "
71 "domains, not type {} domains.", r.domainType());
87 void Inlet1D::showSolution(
const double* x)
89 writelog(
" Mass Flux: {:10.4g} kg/m^2/s \n", m_mdot);
90 writelog(
" Temperature: {:10.4g} K \n", m_temp);
93 for (
size_t k = 0; k < m_flow->phase().nSpecies(); k++) {
94 if (m_yin[k] != 0.0) {
96 m_flow->phase().speciesName(k), m_yin[k]);
103 void Inlet1D::setMoleFractions(
const std::string& xin)
107 m_flow->phase().setMoleFractionsByName(xin);
108 m_flow->phase().getMassFractions(m_yin.data());
113 void Inlet1D::setMoleFractions(
const double* xin)
116 m_flow->phase().setMoleFractions(xin);
117 m_flow->phase().getMassFractions(m_yin.data());
131 m_flow = m_flow_left;
132 }
else if (m_flow_right) {
134 m_flow = m_flow_right;
140 m_nsp = m_flow->phase().nSpecies();
141 m_yin.resize(m_nsp, 0.0);
143 setMoleFractions(m_xstr);
149 void Inlet1D::eval(
size_t jg,
double* xg,
double* rg,
150 integer* diagg,
double rdt)
152 if (jg !=
npos && (jg + 2 < firstPoint() || jg > lastPoint() + 2)) {
156 if (m_ilr == LeftInlet) {
158 double* xb = xg + m_flow->loc();
159 double* rb = rg + m_flow->loc();
167 rb[c_offset_V] -= m_V0;
169 if (m_flow->doEnergy(0)) {
172 rb[c_offset_T] -= m_temp;
175 if (m_flow->fixed_mdot()) {
178 rb[c_offset_L] += m_mdot;
182 m_mdot = m_flow->density(0)*xb[0];
183 rb[c_offset_L] = xb[c_offset_L];
187 for (
size_t k = 0; k < m_nsp; k++) {
188 if (k != m_flow_right->leftExcessSpecies()) {
189 rb[c_offset_Y+k] += m_mdot*m_yin[k];
196 double* rb = rg + loc() - m_flow->nComponents();
197 rb[c_offset_V] -= m_V0;
198 if (m_flow->doEnergy(m_flow->nPoints() - 1)) {
199 rb[c_offset_T] -= m_temp;
201 rb[c_offset_U] += m_mdot;
202 for (
size_t k = 0; k < m_nsp; k++) {
203 if (k != m_flow_left->rightExcessSpecies()) {
204 rb[c_offset_Y+k] += m_mdot * m_yin[k];
212 XML_Node& inlt = Domain1D::save(o, soln);
214 addFloat(inlt,
"temperature", m_temp);
216 for (
size_t k=0; k < m_nsp; k++) {
217 addFloat(inlt,
"massFraction", m_yin[k],
"",
218 m_flow->phase().speciesName(k));
223 void Inlet1D::restore(
const XML_Node& dom,
double* soln,
int loglevel)
225 Domain1D::restore(dom, soln, loglevel);
227 m_temp =
getFloat(dom,
"temperature");
229 m_yin.assign(m_nsp, 0.0);
231 for (
size_t i = 0; i < dom.
nChildren(); i++) {
233 if (node.
name() ==
"massFraction") {
234 size_t k = m_flow->phase().speciesIndex(node.
attrib(
"type"));
250 void Empty1D::eval(
size_t jg,
double* xg,
double* rg,
251 integer* diagg,
double rdt)
257 XML_Node& symm = Domain1D::save(o, soln);
262 void Empty1D::restore(
const XML_Node& dom,
double* soln,
int loglevel)
264 Domain1D::restore(dom, soln, loglevel);
275 void Symm1D::eval(
size_t jg,
double* xg,
double* rg, integer* diagg,
278 if (jg !=
npos && (jg + 2< firstPoint() || jg > lastPoint() + 2)) {
283 double* x = xg + loc();
284 double* r = rg + loc();
285 integer* diag = diagg + loc();
288 size_t nc = m_flow_right->nComponents();
294 rb[c_offset_V] = xb[c_offset_V] - xb[c_offset_V + nc];
295 if (m_flow_right->doEnergy(0)) {
296 rb[c_offset_T] = xb[c_offset_T] - xb[c_offset_T + nc];
301 size_t nc = m_flow_left->nComponents();
307 rb[c_offset_V] = xb[c_offset_V] - xb[c_offset_V - nc];
308 if (m_flow_left->doEnergy(m_flow_left->nPoints() - 1)) {
309 rb[c_offset_T] = xb[c_offset_T] - xb[c_offset_T - nc];
316 XML_Node& symm = Domain1D::save(o, soln);
321 void Symm1D::restore(
const XML_Node& dom,
double* soln,
int loglevel)
323 Domain1D::restore(dom, soln, loglevel);
329 OutletRes1D::OutletRes1D()
333 m_type = cOutletResType;
342 m_flow_right->setViscosityFlag(
false);
345 m_flow_left->setViscosityFlag(
false);
357 double* x = xg +
loc();
358 double* r = rg +
loc();
359 integer* diag = diagg +
loc();
365 rb[c_offset_U] = xb[c_offset_L];
366 if (m_flow_right->doEnergy(0)) {
367 rb[c_offset_T] = xb[c_offset_T] - xb[c_offset_T + nc];
369 for (
size_t k = c_offset_Y; k < nc; k++) {
370 rb[k] = xb[k] - xb[k + nc];
381 if (m_flow_left->fixed_mdot()) {
382 rb[c_offset_U] = xb[c_offset_L];
385 if (m_flow_left->doEnergy(m_flow_left->
nPoints()-1)) {
386 rb[c_offset_T] = xb[c_offset_T] - xb[c_offset_T - nc];
389 for (
size_t k = c_offset_Y; k < nc; k++) {
391 rb[k] = xb[k] - xb[k - nc];
437 m_flow = m_flow_left;
438 }
else if (m_flow_right) {
439 m_flow = m_flow_right;
445 m_yres.resize(m_nsp, 0.0);
454 integer* diagg,
double rdt)
461 double* x = xg +
loc();
462 double* r = rg +
loc();
463 integer* diag = diagg +
loc();
472 rb[c_offset_U] = xb[c_offset_L];
474 if (m_flow_right->doEnergy(0)) {
476 rb[c_offset_T] = xb[c_offset_T] - xb[c_offset_T + nc];
480 for (
size_t k = c_offset_Y; k < nc; k++) {
481 rb[k] = xb[k] - m_yres[k-c_offset_Y];
491 if (!m_flow_left->fixed_mdot()) {
494 rb[c_offset_U] = xb[c_offset_L];
496 if (m_flow_left->doEnergy(m_flow_left->
nPoints()-1)) {
497 rb[c_offset_T] = xb[c_offset_T] - m_temp;
500 for (
size_t k = c_offset_Y; k < nc; k++) {
502 rb[k] = xb[k] - m_yres[k-c_offset_Y];
513 addFloat(outlt,
"temperature", m_temp,
"K");
514 for (
size_t k=0; k < m_nsp; k++) {
515 addFloat(outlt,
"massFraction", m_yres[k],
"",
524 m_temp =
getFloat(dom,
"temperature");
526 m_yres.assign(m_nsp, 0.0);
527 for (
size_t i = 0; i < dom.
nChildren(); i++) {
529 if (node.
name() ==
"massFraction") {
548 integer* diagg,
double rdt)
555 double* x = xg +
loc();
556 double* r = rg +
loc();
561 rb[c_offset_T] = xb[c_offset_T] - m_temp;
568 rb[c_offset_T] = xb[c_offset_T] - m_temp;
576 addFloat(inlt,
"temperature", m_temp);
583 m_temp =
getFloat(dom,
"temperature");
587 void Surf1D::showSolution_s(std::ostream& s,
const double* x)
589 s <<
"------------------- Surface " <<
domainIndex() <<
" ------------------- " << std::endl;
590 s <<
" temperature: " << m_temp <<
" K" << std::endl;
595 ReactingSurf1D::ReactingSurf1D()
603 void ReactingSurf1D::setKineticsMgr(InterfaceKinetics* kin)
606 m_surfindex = kin->surfacePhaseIndex();
607 m_sphase = (SurfPhase*)&kin->thermo(m_surfindex);
625 m_fixed_cov.resize(m_nsp, 0.0);
626 m_fixed_cov[0] = 1.0;
629 for (
size_t n = 0; n < m_nsp; n++) {
630 setBounds(n, -1.0e-5, 2.0);
635 double* x = xg +
loc();
641 integer* diagg,
double rdt)
648 double* x = xg +
loc();
649 double* r = rg +
loc();
650 integer* diag = diagg +
loc();
654 for (
size_t k = 0; k < m_nsp; k++) {
663 size_t leftloc = 0, rightloc = 0;
667 leftloc = m_flow_left->
loc();
668 pnt = m_flow_left->
nPoints() - 1;
669 m_flow_left->
setGas(xg + leftloc, pnt);
673 rightloc = m_flow_right->
loc();
674 m_flow_right->
setGas(xg + rightloc, 0);
682 for (
size_t k = 0; k < m_nsp; k++) {
683 r[k] = m_work[k + ioffset] * m_sphase->
size(k) * rs0;
690 for (
size_t k = 0; k < m_nsp; k++) {
691 r[k] = x[k] - m_fixed_cov[k];
697 double* rb = r + m_nsp;
698 double* xb = x + m_nsp;
699 rb[c_offset_T] = xb[c_offset_T] - m_temp;
706 rb[c_offset_T] = xb[c_offset_T] - m_temp;
710 for (
size_t nth = 0; nth < m_kin->
nPhases(); nth++) {
711 if (&m_kin->
thermo(nth) == left_thermo) {
716 for (
size_t nl = 0; nl < m_left_nsp; nl++) {
718 rb[c_offset_Y+nl] += m_work[nl + l_offset]*mwleft[nl];
726 const double* s = soln +
loc();
729 addFloat(dom,
"temperature", m_temp,
"K");
730 for (
size_t k=0; k < m_nsp; k++) {
740 m_temp =
getFloat(dom,
"temperature");
742 m_fixed_cov.assign(m_nsp, 0.0);
743 for (
size_t i = 0; i < dom.
nChildren(); i++) {
745 if (node.
name() ==
"coverage") {
748 m_fixed_cov[k] = soln[k] = node.
fp_value();
759 writelog(
" Temperature: {:10.4g} K \n", m_temp);
761 for (
size_t k = 0; k < m_nsp; k++) {
Boundary objects for one-dimensional simulations.
Base class for exceptions thrown by Cantera classes.
size_t lastPoint() const
The index of the last (i.e., right-most) grid point belonging to this domain.
size_t domainIndex()
The left-to-right location of this domain.
size_t nComponents() const
Number of components at each grid point.
size_t nPoints() const
Number of grid points in this domain.
virtual XML_Node & save(XML_Node &o, const doublereal *const sol)
Save the current solution for this domain into an XML_Node.
virtual void resize(size_t nv, size_t np)
virtual void restore(const XML_Node &dom, doublereal *soln, int loglevel)
Restore the solution for this domain from an XML_Node.
double prevSoln(size_t n, size_t j) const
Value of component n at point j in the previous solution.
size_t firstPoint() const
The index of the first (i.e., left-most) grid point belonging to this domain.
virtual size_t loc(size_t j=0) const
Location of the start of the local solution vector in the global solution vector,.
thermo_t & thermo(size_t n=0)
This method returns a reference to the nth ThermoPhase object defined in this kinetics mechanism.
size_t nPhases() const
The number of phases participating in the reaction mechanism.
virtual void getNetProductionRates(doublereal *wdot)
Species net production rates [kmol/m^3/s or kmol/m^2/s].
size_t kineticsSpeciesIndex(size_t k, size_t n) const
The location of species k of phase n in species arrays.
size_t nTotalSpecies() const
The total number of species in all phases participating in the kinetics mechanism.
virtual XML_Node & save(XML_Node &o, const double *const soln)
Save the current solution for this domain into an XML_Node.
virtual void eval(size_t jg, double *xg, double *rg, integer *diagg, double rdt)
Evaluate the residual function at point j.
virtual void restore(const XML_Node &dom, double *soln, int loglevel)
Restore the solution for this domain from an XML_Node.
virtual void setMoleFractions(const std::string &xin)
Set the mole fractions by specifying a std::string.
virtual XML_Node & save(XML_Node &o, const double *const soln)
Save the current solution for this domain into an XML_Node.
virtual void eval(size_t jg, double *xg, double *rg, integer *diagg, double rdt)
Evaluate the residual function at point j.
virtual void restore(const XML_Node &dom, double *soln, int loglevel)
Restore the solution for this domain from an XML_Node.
virtual void setMoleFractions(const double *const x)
Set the mole fractions to the specified values.
size_t nSpecies() const
Returns the number of species in the phase.
void setMoleFractionsByName(const compositionMap &xMap)
Set the species mole fractions by name.
const vector_fp & molecularWeights() const
Return a const reference to the internal vector of molecular weights.
std::string speciesName(size_t k) const
Name of the species with index k.
size_t speciesIndex(const std::string &name) const
Returns the index of a species named 'name' within the Phase object.
virtual void setTemperature(const doublereal temp)
Set the internally stored temperature of the phase (K).
void getMassFractions(double *const y) const
Get the species mass fractions.
virtual XML_Node & save(XML_Node &o, const double *const soln)
Save the current solution for this domain into an XML_Node.
virtual std::string componentName(size_t n) const
Name of the nth component. May be overloaded.
virtual void showSolution(const double *x)
Print the solution.
virtual void eval(size_t jg, double *xg, double *rg, integer *diagg, double rdt)
Evaluate the residual function at point j.
virtual void resetBadValues(double *xg)
virtual void restore(const XML_Node &dom, double *soln, int loglevel)
Restore the solution for this domain from an XML_Node.
size_t rightExcessSpecies() const
Index of the species on the right boundary with the largest mass fraction.
void setGas(const doublereal *x, size_t j)
Set the gas object state to be consistent with the solution at point j.
virtual XML_Node & save(XML_Node &o, const double *const soln)
Save the current solution for this domain into an XML_Node.
virtual void eval(size_t jg, double *xg, double *rg, integer *diagg, double rdt)
Evaluate the residual function at point j.
virtual void restore(const XML_Node &dom, double *soln, int loglevel)
Restore the solution for this domain from an XML_Node.
void setCoveragesNoNorm(const doublereal *theta)
Set the surface site fractions to a specified state.
void getCoverages(doublereal *theta) const
Return a vector of surface coverages.
virtual double size(size_t k) const
Returns the number of sites occupied by one molecule of species k.
doublereal siteDensity()
Returns the site density.
void setCoverages(const doublereal *theta)
Set the surface site fractions to a specified state.
Base class for a phase with thermodynamic properties.
Class XML_Node is a tree-based representation of the contents of an XML file.
std::string attrib(const std::string &attr) const
Function returns the value of an attribute.
std::string name() const
Returns the name of the XML node.
void addAttribute(const std::string &attrib, const std::string &value)
Add or modify an attribute of the current node.
doublereal fp_value() const
Return the value of an XML node as a single double.
size_t nChildren(bool discardComments=false) const
Return the number of children.
XML_Node & child(const size_t n) const
Return a changeable reference to the n'th child of the current node.
CTML ("Cantera Markup Language") is the variant of XML that Cantera uses to store data.
const size_t npos
index returned by functions to indicate "no position"
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
void writelog(const std::string &fmt, const Args &... args)
Write a formatted message to the screen.
Namespace for the Cantera kernel.
doublereal getFloat(const XML_Node &parent, const std::string &name, const std::string &type)
Get a floating-point value from a child element.
void addFloat(XML_Node &node, const std::string &title, const doublereal val, const std::string &units, const std::string &type, const doublereal minval, const doublereal maxval)
This function adds a child node with the name, "float", with a value consisting of a single floating ...