16Boundary1D::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;
29void 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_left_nv = r.nComponents();
47 if (m_left_nv > c_offset_Y) {
48 m_left_nsp = m_left_nv - c_offset_Y;
52 m_left_loc = container().start(m_index-1);
53 m_left_points = r.nPoints();
54 m_flow_left =
dynamic_cast<StFlow*
>(&r);
55 if (m_flow_left !=
nullptr) {
56 m_phase_left = &m_flow_left->phase();
59 throw CanteraError(
"Boundary1D::_init",
60 "Boundary domains can only be connected on the left to flow "
61 "domains, not type {} domains.", r.domainType());
66 if (m_index + 1 < container().nDomains()) {
67 Domain1D& r = container().domain(m_index+1);
68 if (!r.isConnector()) {
69 m_right_nv = r.nComponents();
70 if (m_right_nv > c_offset_Y) {
71 m_right_nsp = m_right_nv - c_offset_Y;
75 m_right_loc = container().start(m_index+1);
76 m_flow_right =
dynamic_cast<StFlow*
>(&r);
77 if (m_flow_right !=
nullptr) {
78 m_phase_right = &m_flow_right->phase();
81 throw CanteraError(
"Boundary1D::_init",
82 "Boundary domains can only be connected on the right to flow "
83 "domains, not type {} domains.", r.domainType());
99void Inlet1D::showSolution(
const double* x)
101 writelog(
" Mass Flux: {:10.4g} kg/m^2/s \n", m_mdot);
102 writelog(
" Temperature: {:10.4g} K \n", m_temp);
105 for (
size_t k = 0; k < m_flow->phase().nSpecies(); k++) {
106 if (m_yin[k] != 0.0) {
108 m_flow->phase().speciesName(k), m_yin[k]);
115void Inlet1D::setMoleFractions(
const std::string& xin)
119 m_flow->phase().setMoleFractionsByName(xin);
120 m_flow->phase().getMassFractions(m_yin.data());
125void Inlet1D::setMoleFractions(
const double* xin)
128 m_flow->phase().setMoleFractions(xin);
129 m_flow->phase().getMassFractions(m_yin.data());
143 m_flow = m_flow_left;
144 }
else if (m_flow_right) {
146 m_flow = m_flow_right;
152 m_nsp = m_flow->phase().nSpecies();
153 m_yin.resize(m_nsp, 0.0);
155 setMoleFractions(m_xstr);
161void Inlet1D::eval(
size_t jg,
double* xg,
double* rg,
162 integer* diagg,
double rdt)
164 if (jg !=
npos && (jg + 2 < firstPoint() || jg > lastPoint() + 2)) {
168 if (m_ilr == LeftInlet) {
170 double* xb = xg + m_flow->loc();
171 double* rb = rg + m_flow->loc();
179 rb[c_offset_V] -= m_V0;
181 if (m_flow->doEnergy(0)) {
184 rb[c_offset_T] -= m_temp;
187 if (m_flow->fixed_mdot()) {
190 rb[c_offset_L] += m_mdot;
194 m_mdot = m_flow->density(0)*xb[0];
195 rb[c_offset_L] = xb[c_offset_L];
199 for (
size_t k = 0; k < m_nsp; k++) {
200 if (k != m_flow_right->leftExcessSpecies()) {
201 rb[c_offset_Y+k] += m_mdot*m_yin[k];
208 double* rb = rg + loc() - m_flow->nComponents();
209 rb[c_offset_V] -= m_V0;
210 if (m_flow->doEnergy(m_flow->nPoints() - 1)) {
211 rb[c_offset_T] -= m_temp;
213 rb[c_offset_U] += m_mdot;
214 for (
size_t k = 0; k < m_nsp; k++) {
215 if (k != m_flow_left->rightExcessSpecies()) {
216 rb[c_offset_Y+k] += m_mdot * m_yin[k];
224 XML_Node& inlt = Domain1D::save(o, soln);
226 addFloat(inlt,
"temperature", m_temp);
228 for (
size_t k=0; k < m_nsp; k++) {
229 addFloat(inlt,
"massFraction", m_yin[k],
"",
230 m_flow->phase().speciesName(k));
235void Inlet1D::restore(
const XML_Node& dom,
double* soln,
int loglevel)
237 Domain1D::restore(dom, soln, loglevel);
239 m_temp =
getFloat(dom,
"temperature");
241 m_yin.assign(m_nsp, 0.0);
243 for (
size_t i = 0; i < dom.
nChildren(); i++) {
245 if (node.
name() ==
"massFraction") {
246 size_t k = m_flow->phase().speciesIndex(node.
attrib(
"type"));
255AnyMap Inlet1D::serialize(
const double* soln)
const
257 AnyMap state = Boundary1D::serialize(soln);
258 state[
"type"] =
"inlet";
259 state[
"temperature"] = m_temp;
260 state[
"mass-flux"] = m_mdot;
262 for (
size_t k = 0; k < m_nsp; k++) {
263 if (m_yin[k] != 0.0) {
264 Y[m_flow->phase().speciesName(k)] = m_yin[k];
267 state[
"mass-fractions"] = std::move(Y);
271void Inlet1D::restore(
const AnyMap& state,
double* soln,
int loglevel)
273 Boundary1D::restore(state, soln, loglevel);
274 m_mdot = state[
"mass-flux"].asDouble();
275 m_temp = state[
"temperature"].asDouble();
276 const auto& Y = state[
"mass-fractions"].as<
AnyMap>();
278 for (
size_t k = 0; k < m_nsp; k++) {
279 m_yin[k] = Y.getDouble(thermo.speciesName(k), 0.0);
284 for (
auto& item : Y) {
285 if (thermo.speciesIndex(item.first) ==
npos) {
286 warn_user(
"Inlet1D::restore",
"Phase '{}' does not contain a species "
287 "named '{}'\n which was specified as having a mass fraction of {}.",
288 thermo.name(), item.first, item.second.asDouble());
301void Empty1D::eval(
size_t jg,
double* xg,
double* rg,
302 integer* diagg,
double rdt)
308 XML_Node& symm = Domain1D::save(o, soln);
313void Empty1D::restore(
const XML_Node& dom,
double* soln,
int loglevel)
315 Domain1D::restore(dom, soln, loglevel);
319AnyMap Empty1D::serialize(
const double* soln)
const
321 AnyMap state = Boundary1D::serialize(soln);
322 state[
"type"] =
"empty";
333void Symm1D::eval(
size_t jg,
double* xg,
double* rg, integer* diagg,
336 if (jg !=
npos && (jg + 2< firstPoint() || jg > lastPoint() + 2)) {
341 double* x = xg + loc();
342 double* r = rg + loc();
343 integer* diag = diagg + loc();
346 size_t nc = m_flow_right->nComponents();
352 rb[c_offset_V] = xb[c_offset_V] - xb[c_offset_V + nc];
353 if (m_flow_right->doEnergy(0)) {
354 rb[c_offset_T] = xb[c_offset_T] - xb[c_offset_T + nc];
359 size_t nc = m_flow_left->nComponents();
365 rb[c_offset_V] = xb[c_offset_V] - xb[c_offset_V - nc];
366 if (m_flow_left->doEnergy(m_flow_left->nPoints() - 1)) {
367 rb[c_offset_T] = xb[c_offset_T] - xb[c_offset_T - nc];
374 XML_Node& symm = Domain1D::save(o, soln);
379void Symm1D::restore(
const XML_Node& dom,
double* soln,
int loglevel)
381 Domain1D::restore(dom, soln, loglevel);
385AnyMap Symm1D::serialize(
const double* soln)
const
387 AnyMap state = Boundary1D::serialize(soln);
388 state[
"type"] =
"symmetry";
394OutletRes1D::OutletRes1D()
398 m_type = cOutletResType;
407 m_flow_right->setViscosityFlag(
false);
410 m_flow_left->setViscosityFlag(
false);
422 double* x = xg +
loc();
423 double* r = rg +
loc();
424 integer* diag = diagg +
loc();
430 rb[c_offset_U] = xb[c_offset_L];
431 if (m_flow_right->doEnergy(0)) {
432 rb[c_offset_T] = xb[c_offset_T] - xb[c_offset_T + nc];
434 for (
size_t k = c_offset_Y; k < nc; k++) {
435 rb[k] = xb[k] - xb[k + nc];
446 if (m_flow_left->fixed_mdot()) {
447 rb[c_offset_U] = xb[c_offset_L];
450 if (m_flow_left->doEnergy(m_flow_left->
nPoints()-1)) {
451 rb[c_offset_T] = xb[c_offset_T] - xb[c_offset_T - nc];
454 for (
size_t k = c_offset_Y; k < nc; k++) {
456 rb[k] = xb[k] - xb[k - nc];
479 state[
"type"] =
"outlet";
509 m_flow = m_flow_left;
510 }
else if (m_flow_right) {
511 m_flow = m_flow_right;
517 m_yres.resize(m_nsp, 0.0);
526 integer* diagg,
double rdt)
533 double* x = xg +
loc();
534 double* r = rg +
loc();
535 integer* diag = diagg +
loc();
544 rb[c_offset_U] = xb[c_offset_L];
546 if (m_flow_right->doEnergy(0)) {
548 rb[c_offset_T] = xb[c_offset_T] - xb[c_offset_T + nc];
552 for (
size_t k = c_offset_Y; k < nc; k++) {
553 rb[k] = xb[k] - m_yres[k-c_offset_Y];
563 if (!m_flow_left->fixed_mdot()) {
566 rb[c_offset_U] = xb[c_offset_L];
568 if (m_flow_left->doEnergy(m_flow_left->
nPoints()-1)) {
569 rb[c_offset_T] = xb[c_offset_T] - m_temp;
572 for (
size_t k = c_offset_Y; k < nc; k++) {
574 rb[k] = xb[k] - m_yres[k-c_offset_Y];
585 addFloat(outlt,
"temperature", m_temp,
"K");
586 for (
size_t k=0; k < m_nsp; k++) {
587 addFloat(outlt,
"massFraction", m_yres[k],
"",
596 m_temp =
getFloat(dom,
"temperature");
598 m_yres.assign(m_nsp, 0.0);
599 for (
size_t i = 0; i < dom.
nChildren(); i++) {
601 if (node.
name() ==
"massFraction") {
615 state[
"type"] =
"outlet-reservoir";
616 state[
"temperature"] = m_temp;
618 for (
size_t k = 0; k < m_nsp; k++) {
619 if (m_yres[k] != 0.0) {
623 state[
"mass-fractions"] = std::move(Y);
630 m_temp = state[
"temperature"].asDouble();
631 const auto& Y = state[
"mass-fractions"].as<
AnyMap>();
633 for (
size_t k = 0; k < m_nsp; k++) {
634 m_yres[k] = Y.getDouble(thermo.speciesName(k), 0.0);
639 for (
auto& item : Y) {
640 if (thermo.speciesIndex(item.first) ==
npos) {
641 warn_user(
"OutletRes1D::restore",
"Phase '{}' does not contain a "
642 "species named '{}'\nwhich was specified as having a mass "
644 thermo.name(), item.first, item.second.asDouble());
658 integer* diagg,
double rdt)
665 double* x = xg +
loc();
666 double* r = rg +
loc();
671 rb[c_offset_T] = xb[c_offset_T] - m_temp;
678 rb[c_offset_T] = xb[c_offset_T] - m_temp;
686 addFloat(inlt,
"temperature", m_temp);
693 m_temp =
getFloat(dom,
"temperature");
700 state[
"type"] =
"surface";
701 state[
"temperature"] = m_temp;
708 m_temp = state[
"temperature"].asDouble();
711void Surf1D::showSolution_s(std::ostream& s,
const double* x)
713 s <<
"------------------- Surface " <<
domainIndex() <<
" ------------------- " << std::endl;
714 s <<
" temperature: " << m_temp <<
" K" << std::endl;
719 writelog(
" Temperature: {:10.4g} K \n\n", m_temp);
724ReactingSurf1D::ReactingSurf1D()
732void ReactingSurf1D::setKineticsMgr(InterfaceKinetics* kin)
735 m_surfindex = kin->surfacePhaseIndex();
736 m_sphase = (SurfPhase*)&kin->thermo(m_surfindex);
754 m_fixed_cov.resize(m_nsp, 0.0);
755 m_fixed_cov[0] = 1.0;
758 for (
size_t n = 0; n < m_nsp; n++) {
759 setBounds(n, -1.0e-5, 2.0);
764 double* x = xg +
loc();
770 integer* diagg,
double rdt)
777 double* x = xg +
loc();
778 double* r = rg +
loc();
779 integer* diag = diagg +
loc();
783 for (
size_t k = 0; k < m_nsp; k++) {
792 size_t leftloc = 0, rightloc = 0;
796 leftloc = m_flow_left->
loc();
797 pnt = m_flow_left->
nPoints() - 1;
798 m_flow_left->
setGas(xg + leftloc, pnt);
802 rightloc = m_flow_right->
loc();
803 m_flow_right->
setGas(xg + rightloc, 0);
811 for (
size_t k = 0; k < m_nsp; k++) {
812 r[k] = m_work[k + ioffset] * m_sphase->
size(k) * rs0;
819 for (
size_t k = 0; k < m_nsp; k++) {
820 r[k] = x[k] - m_fixed_cov[k];
826 double* rb = r + m_nsp;
827 double* xb = x + m_nsp;
828 rb[c_offset_T] = xb[c_offset_T] - m_temp;
835 rb[c_offset_T] = xb[c_offset_T] - m_temp;
839 for (
size_t nth = 0; nth < m_kin->
nPhases(); nth++) {
840 if (&m_kin->
thermo(nth) == left_thermo) {
845 for (
size_t nl = 0; nl < m_left_nsp; nl++) {
847 rb[c_offset_Y+nl] += m_work[nl + l_offset]*mwleft[nl];
855 const double* s = soln +
loc();
858 addFloat(dom,
"temperature", m_temp,
"K");
859 for (
size_t k=0; k < m_nsp; k++) {
869 m_temp =
getFloat(dom,
"temperature");
871 m_fixed_cov.assign(m_nsp, 0.0);
872 for (
size_t i = 0; i < dom.
nChildren(); i++) {
874 if (node.
name() ==
"coverage") {
877 m_fixed_cov[k] = soln[k] = node.
fp_value();
889 state[
"type"] =
"reacting-surface";
890 state[
"temperature"] = m_temp;
891 state[
"phase"][
"name"] = m_sphase->
name();
893 state[
"phase"][
"source"] = source.
empty() ?
"<unknown>" : source.
asString();
895 for (
size_t k = 0; k < m_nsp; k++) {
898 state[
"coverages"] = std::move(cov);
906 m_temp = state[
"temperature"].asDouble();
907 const auto& cov = state[
"coverages"].as<
AnyMap>();
908 for (
size_t k = 0; k < m_nsp; k++) {
914 for (
auto& item : cov) {
916 warn_user(
"OutletRes1D::restore",
"Phase '{}' does not contain a "
917 "species named '{}'\nwhich was specified as having a coverage "
919 m_sphase->
name(), item.first, item.second.asDouble());
927 writelog(
" Temperature: {:10.4g} K \n", m_temp);
929 for (
size_t k = 0; k < m_nsp; k++) {
Boundary objects for one-dimensional simulations.
const AnyValue & getMetadata(const std::string &key) const
Get a value from the metadata applicable to the AnyMap tree containing this node.
A map of string keys to values whose type can vary at runtime.
double getDouble(const std::string &key, double default_) const
If key exists, return it as a double, otherwise return default_.
A wrapper for a variable whose type is determined at runtime.
const std::string & asString() const
Return the held value, if it is a string.
bool empty() const
Return boolean indicating whether AnyValue is empty.
Base class for exceptions thrown by Cantera classes.
size_t lastPoint() const
The index of the last (that is, 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.
virtual AnyMap serialize(const double *soln) const
Save the state of this domain as an AnyMap.
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 (that is, 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,.
ThermoPhase & 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 AnyMap serialize(const double *soln) const
Save the state of this domain as an AnyMap.
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 AnyMap serialize(const double *soln) const
Save the state of this domain as an AnyMap.
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.
std::string name() const
Return the name of the phase.
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.
virtual void setTemperature(double temp)
Set the internally stored temperature of the phase (K).
size_t speciesIndex(const std::string &name) const
Returns the index of a species named 'name' within the Phase object.
void getMassFractions(double *const y) const
Get the species mass fractions.
virtual AnyMap serialize(const double *soln) const
Save the state of this domain as an AnyMap.
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 AnyMap serialize(const double *soln) const
Save the state of this domain as an AnyMap.
virtual XML_Node & save(XML_Node &o, const double *const soln)
Save the current solution for this domain into an XML_Node.
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 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.
double siteDensity() const
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.
const AnyMap & input() const
Access input data associated with the phase description.
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.
void writelog(const std::string &fmt, const Args &... args)
Write a formatted message to the screen.
Namespace for the Cantera kernel.
const size_t npos
index returned by functions to indicate "no position"
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 &titleString, const doublereal value, const std::string &unitsString="", const std::string &typeString="", const doublereal minval=Undef, const doublereal maxval=Undef)
This function adds a child node with the name, "float", with a value consisting of a single floating ...
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
void warn_user(const std::string &method, const std::string &msg, const Args &... args)
Print a user warning raised from method as CanteraWarning.