Cantera  2.2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Phase.cpp
Go to the documentation of this file.
1 /**
2  * @file Phase.cpp
3  * Definition file for class Phase.
4  */
5 
6 // Copyright 2001 California Institute of Technology
7 
8 #include "cantera/thermo/Phase.h"
11 #include "cantera/base/ctml.h"
13 
14 using namespace std;
15 
16 namespace Cantera
17 {
18 
19 Phase::Phase() :
20  m_kk(0),
21  m_ndim(3),
22  m_undefinedElementBehavior(UndefElement::error),
23  m_xml(new XML_Node("phase")),
24  m_id("<phase>"),
25  m_temp(0.001),
26  m_dens(0.001),
27  m_mmw(0.0),
28  m_stateNum(-1),
29  m_mm(0),
30  m_elem_type(0),
31  realNumberRangeBehavior_(THROWON_OVERFLOW_DEBUGMODEONLY_CTRB)
32 {
33 }
34 
35 Phase::Phase(const Phase& right) :
36  m_kk(0),
37  m_ndim(3),
38  m_undefinedElementBehavior(right.m_undefinedElementBehavior),
39  m_xml(0),
40  m_id("<phase>"),
41  m_temp(0.001),
42  m_dens(0.001),
43  m_mmw(0.0),
44  m_stateNum(-1),
45  m_mm(0),
46  m_elem_type(0),
47  realNumberRangeBehavior_(THROWON_OVERFLOW_DEBUGMODEONLY_CTRB)
48 {
49  // Use the assignment operator to do the actual copying
50  operator=(right);
51 }
52 
54 {
55  // Check for self assignment.
56  if (this == &right) {
57  return *this;
58  }
59 
60  // Handle our own data
61  m_kk = right.m_kk;
62  m_ndim = right.m_ndim;
64  m_temp = right.m_temp;
65  m_dens = right.m_dens;
66  m_mmw = right.m_mmw;
67  m_ym = right.m_ym;
68  m_y = right.m_y;
69  m_molwts = right.m_molwts;
70  m_rmolwts = right.m_rmolwts;
71  m_stateNum = -1;
72 
77 
78  m_mm = right.m_mm;
82  m_entropy298 = right.m_entropy298;
83  m_elem_type = right.m_elem_type;
84  /*
85  * This is a little complicated. -> Because we delete m_xml
86  * in the destructor, we own m_xml completely, and we need
87  * to have our own individual copies of the XML data tree
88  * in each object
89  */
90  if (m_xml) {
91  XML_Node* rroot = &(m_xml->root());
92  delete rroot;
93  m_xml = 0;
94  }
95  if (right.m_xml) {
96  XML_Node *rroot = &(right.m_xml->root());
97  XML_Node *root_xml = new XML_Node();
98  (rroot)->copy(root_xml);
99  m_xml = findXMLPhase(root_xml, right.m_xml->id());
100  if (!m_xml) {
101  throw CanteraError("Phase::operator=()", "Confused: Couldn't find original phase " + right.m_xml->id());
102  }
103  if (&(m_xml->root()) != root_xml) {
104  throw CanteraError("Phase::operator=()", "confused: root changed");
105  }
106  }
107  m_id = right.m_id;
108  m_name = right.m_name;
110 
111  return *this;
112 }
113 
115 {
116  if (m_xml) {
117  XML_Node* xroot = &(m_xml->root());
118  delete xroot;
119  }
120  m_xml = 0;
121 }
122 
124 {
125  return *m_xml;
126 }
127 
129 {
130  XML_Node* xroot = &(xmlPhase.root());
131  XML_Node *root_xml = new XML_Node();
132  (xroot)->copy(root_xml);
133  if (m_xml) {
134  XML_Node *rOld = &(m_xml->root());
135  delete rOld;
136  m_xml = 0;
137  }
138  m_xml = findXMLPhase(root_xml, xmlPhase.id());
139  if (!m_xml) {
140  throw CanteraError("Phase::setXMLdata()", "XML 'phase' node not found");
141  }
142  if (&(m_xml->root()) != root_xml) {
143  throw CanteraError("Phase::setXMLdata()", "Root XML node not found");
144  }
145 }
146 
147 std::string Phase::id() const
148 {
149  return m_id;
150 }
151 
152 void Phase::setID(const std::string& id_)
153 {
154  m_id = id_;
155 }
156 
157 std::string Phase::name() const
158 {
159  return m_name;
160 }
161 
162 void Phase::setName(const std::string& nm)
163 {
164  m_name = nm;
165 }
166 
167 size_t Phase::nElements() const
168 {
169  return m_mm;
170 }
171 
172 void Phase::checkElementIndex(size_t m) const
173 {
174  if (m >= m_mm) {
175  throw IndexError("checkElementIndex", "elements", m, m_mm-1);
176  }
177 }
178 
179 void Phase::checkElementArraySize(size_t mm) const
180 {
181  if (m_mm > mm) {
182  throw ArraySizeError("checkElementArraySize", mm, m_mm);
183  }
184 }
185 
186 string Phase::elementName(size_t m) const
187 {
189  return m_elementNames[m];
190 }
191 
192 size_t Phase::elementIndex(const std::string& elementName) const
193 {
194  for (size_t i = 0; i < m_mm; i++) {
195  if (m_elementNames[i] == elementName) {
196  return i;
197  }
198  }
199  return npos;
200 }
201 
202 const vector<string>& Phase::elementNames() const
203 {
204  return m_elementNames;
205 }
206 
207 doublereal Phase::atomicWeight(size_t m) const
208 {
209  return m_atomicWeights[m];
210 }
211 
212 doublereal Phase::entropyElement298(size_t m) const
213 {
215  "Elements::entropy298",
216  "Entropy at 298 K of element is unknown");
217  AssertTrace(m < m_mm);
218  return m_entropy298[m];
219 }
220 
222 {
223  return m_atomicWeights;
224 }
225 
226 int Phase::atomicNumber(size_t m) const
227 {
228  return m_atomicNumbers[m];
229 }
230 
231 int Phase::elementType(size_t m) const
232 {
233  return m_elem_type[m];
234 }
235 
236 int Phase::changeElementType(int m, int elem_type)
237 {
238  int old = m_elem_type[m];
239  m_elem_type[m] = elem_type;
240  return old;
241 }
242 
243 doublereal Phase::nAtoms(size_t k, size_t m) const
244 {
247  return m_speciesComp[m_mm * k + m];
248 }
249 
250 void Phase::getAtoms(size_t k, double* atomArray) const
251 {
252  for (size_t m = 0; m < m_mm; m++) {
253  atomArray[m] = (double) m_speciesComp[m_mm * k + m];
254  }
255 }
256 
257 size_t Phase::speciesIndex(const std::string& nameStr) const
258 {
259  if (nameStr.find(':') != npos) {
260  std::string pn;
261  std::string sn = parseSpeciesName(nameStr, pn);
262  if (pn == "" || pn == m_name || pn == m_id) {
263  return getValue(m_speciesIndices, sn, npos);
264  } else {
265  return npos;
266  }
267  } else {
268  return getValue(m_speciesIndices, nameStr, npos);
269  }
270 }
271 
272 string Phase::speciesName(size_t k) const
273 {
275  return m_speciesNames[k];
276 }
277 
278 const vector<string>& Phase::speciesNames() const
279 {
280  return m_speciesNames;
281 }
282 
283 void Phase::checkSpeciesIndex(size_t k) const
284 {
285  if (k >= m_kk) {
286  throw IndexError("checkSpeciesIndex", "species", k, m_kk-1);
287  }
288 }
289 
290 void Phase::checkSpeciesArraySize(size_t kk) const
291 {
292  if (m_kk > kk) {
293  throw ArraySizeError("checkSpeciesArraySize", kk, m_kk);
294  }
295 }
296 
297 std::string Phase::speciesSPName(int k) const
298 {
299  return m_name + ":" + speciesName(k);
300 }
301 
302 void Phase::saveState(vector_fp& state) const
303 {
304  state.resize(nSpecies() + 2);
305  saveState(state.size(),&(state[0]));
306 }
307 void Phase::saveState(size_t lenstate, doublereal* state) const
308 {
309  state[0] = temperature();
310  state[1] = density();
311  getMassFractions(state + 2);
312 }
313 
314 void Phase::restoreState(const vector_fp& state)
315 {
316  restoreState(state.size(),&state[0]);
317 }
318 
319 void Phase::restoreState(size_t lenstate, const doublereal* state)
320 {
321  if (lenstate >= nSpecies() + 2) {
322  setMassFractions_NoNorm(state + 2);
323  setTemperature(state[0]);
324  setDensity(state[1]);
325  } else {
326  throw ArraySizeError("Phase::restoreState",
327  lenstate,nSpecies()+2);
328  }
329 }
330 
331 void Phase::setMoleFractions(const doublereal* const x)
332 {
333  // Use m_y as a temporary work vector for the non-negative mole fractions
334  doublereal norm = 0.0;
335  /*
336  * sum is calculated below as the unnormalized molecular weight
337  */
338  doublereal sum = 0;
339  for (size_t k = 0; k < m_kk; k++) {
340  double xk = std::max(x[k], 0.0); // Ignore negative mole fractions
341  m_y[k] = xk;
342  norm += xk;
343  sum += m_molwts[k] * xk;
344  }
345  /*
346  * Set m_ym_ to the normalized mole fractions divided by the normalized mean molecular weight:
347  * m_ym_k = X_k / (sum_k X_k M_k)
348  */
349  const doublereal invSum = 1.0/sum;
350  for (size_t k=0; k < m_kk; k++) {
351  m_ym[k] = m_y[k]*invSum;
352  }
353  /*
354  * Now set m_y to the normalized mass fractions
355  * m_y = X_k M_k / (sum_k X_k M_k)
356  */
357  for (size_t k=0; k < m_kk; k++) {
358  m_y[k] = m_ym[k] * m_molwts[k];
359  }
360  /*
361  * Calculate the normalized molecular weight
362  */
363  m_mmw = sum/norm;
364  m_stateNum++;
365 }
366 
367 void Phase::setMoleFractions_NoNorm(const doublereal* const x)
368 {
369  m_mmw = dot(x, x + m_kk, m_molwts.begin());
370  transform(x, x + m_kk, m_ym.begin(), timesConstant<double>(1.0/m_mmw));
371  transform(m_ym.begin(), m_ym.begin() + m_kk, m_molwts.begin(),
372  m_y.begin(), multiplies<double>());
373  m_stateNum++;
374 }
375 
377 {
378  vector_fp mf(m_kk, 0.0);
379  for (size_t k = 0; k < m_kk; k++) {
380  mf[k] = std::max(getValue(xMap, speciesName(k), 0.0), 0.0);
381  }
382  setMoleFractions(&mf[0]);
383 }
384 
385 void Phase::setMoleFractionsByName(const std::string& x)
386 {
388 }
389 
390 void Phase::setMassFractions(const doublereal* const y)
391 {
392  for (size_t k = 0; k < m_kk; k++) {
393  m_y[k] = std::max(y[k], 0.0); // Ignore negative mass fractions
394  }
395  doublereal norm = accumulate(m_y.begin(), m_y.end(), 0.0);
396  scale(m_y.begin(), m_y.end(), m_y.begin(), 1.0/norm);
397 
398  transform(m_y.begin(), m_y.end(), m_rmolwts.begin(),
399  m_ym.begin(), multiplies<double>());
400  m_mmw = 1.0 / accumulate(m_ym.begin(), m_ym.end(), 0.0);
401  m_stateNum++;
402 }
403 
404 void Phase::setMassFractions_NoNorm(const doublereal* const y)
405 {
406  doublereal sum = 0.0;
407  copy(y, y + m_kk, m_y.begin());
408  transform(m_y.begin(), m_y.end(), m_rmolwts.begin(), m_ym.begin(),
409  multiplies<double>());
410  sum = accumulate(m_ym.begin(), m_ym.end(), 0.0);
411  m_mmw = 1.0/sum;
412  m_stateNum++;
413 }
414 
416 {
417  vector_fp mf(m_kk, 0.0);
418  for (size_t k = 0; k < m_kk; k++) {
419  mf[k] = std::max(getValue(yMap, speciesName(k), 0.0), 0.0);
420  }
421  setMassFractions(&mf[0]);
422 }
423 
424 void Phase::setMassFractionsByName(const std::string& y)
425 {
427 }
428 
429 void Phase::setState_TRX(doublereal t, doublereal dens, const doublereal* x)
430 {
431  setMoleFractions(x);
432  setTemperature(t);
433  setDensity(dens);
434 }
435 
436 void Phase::setState_TNX(doublereal t, doublereal n, const doublereal* x)
437 {
438  setMoleFractions(x);
439  setTemperature(t);
440  setMolarDensity(n);
441 }
442 
443 void Phase::setState_TRX(doublereal t, doublereal dens, const compositionMap& x)
444 {
446  setTemperature(t);
447  setDensity(dens);
448 }
449 
450 void Phase::setState_TRY(doublereal t, doublereal dens, const doublereal* y)
451 {
452  setMassFractions(y);
453  setTemperature(t);
454  setDensity(dens);
455 }
456 
457 void Phase::setState_TRY(doublereal t, doublereal dens, const compositionMap& y)
458 {
460  setTemperature(t);
461  setDensity(dens);
462 }
463 
464 void Phase::setState_TR(doublereal t, doublereal rho)
465 {
466  setTemperature(t);
467  setDensity(rho);
468 }
469 
470 void Phase::setState_TX(doublereal t, doublereal* x)
471 {
472  setTemperature(t);
473  setMoleFractions(x);
474 }
475 
476 void Phase::setState_TY(doublereal t, doublereal* y)
477 {
478  setTemperature(t);
479  setMassFractions(y);
480 }
481 
482 void Phase::setState_RX(doublereal rho, doublereal* x)
483 {
484  setMoleFractions(x);
485  setDensity(rho);
486 }
487 
488 void Phase::setState_RY(doublereal rho, doublereal* y)
489 {
490  setMassFractions(y);
491  setDensity(rho);
492 }
493 
494 doublereal Phase::molecularWeight(size_t k) const
495 {
497  return m_molwts[k];
498 }
499 
501 {
502  const vector_fp& mw = molecularWeights();
503  if (weights.size() < mw.size()) {
504  weights.resize(mw.size());
505  }
506  copy(mw.begin(), mw.end(), weights.begin());
507 }
508 
509 void Phase::getMolecularWeights(doublereal* weights) const
510 {
511  const vector_fp& mw = molecularWeights();
512  copy(mw.begin(), mw.end(), weights);
513 }
514 
516 {
517  return m_molwts;
518 }
519 
521 {
522  warn_deprecated("void Phase::getMoleFractionsByName(compositionMap&)",
523  "To be removed after Cantera 2.2. Use"
524  " 'compositionMap getMoleFractionsByName(double threshold)'"
525  " instead");
526  x.clear();
527  for (size_t k = 0; k < m_kk; k++) {
528  x[speciesName(k)] = Phase::moleFraction(k);
529  }
530 }
531 
533 {
534  compositionMap comp;
535  for (size_t k = 0; k < m_kk; k++) {
536  double x = moleFraction(k);
537  if (x > threshold) {
538  comp[speciesName(k)] = x;
539  }
540  }
541  return comp;
542 }
543 
545 {
546  compositionMap comp;
547  for (size_t k = 0; k < m_kk; k++) {
548  double x = massFraction(k);
549  if (x > threshold) {
550  comp[speciesName(k)] = x;
551  }
552  }
553  return comp;
554 }
555 
556 void Phase::getMoleFractions(doublereal* const x) const
557 {
558  scale(m_ym.begin(), m_ym.end(), x, m_mmw);
559 }
560 
561 doublereal Phase::moleFraction(size_t k) const
562 {
564  return m_ym[k] * m_mmw;
565 }
566 
567 doublereal Phase::moleFraction(const std::string& nameSpec) const
568 {
569  size_t iloc = speciesIndex(nameSpec);
570  if (iloc != npos) {
571  return moleFraction(iloc);
572  } else {
573  return 0.0;
574  }
575 }
576 
577 const doublereal* Phase::moleFractdivMMW() const
578 {
579  return &m_ym[0];
580 }
581 
582 doublereal Phase::massFraction(size_t k) const
583 {
585  return m_y[k];
586 }
587 
588 doublereal Phase::massFraction(const std::string& nameSpec) const
589 {
590  size_t iloc = speciesIndex(nameSpec);
591  if (iloc != npos) {
592  return massFractions()[iloc];
593  } else {
594  return 0.0;
595  }
596 }
597 
598 void Phase::getMassFractions(doublereal* const y) const
599 {
600  copy(m_y.begin(), m_y.end(), y);
601 }
602 
603 doublereal Phase::concentration(const size_t k) const
604 {
606  return m_y[k] * m_dens * m_rmolwts[k] ;
607 }
608 
609 void Phase::getConcentrations(doublereal* const c) const
610 {
611  scale(m_ym.begin(), m_ym.end(), c, m_dens);
612 }
613 
614 void Phase::setConcentrations(const doublereal* const conc)
615 {
616  // Use m_y as temporary storage for non-negative concentrations
617  doublereal sum = 0.0, norm = 0.0;
618  for (size_t k = 0; k != m_kk; ++k) {
619  double ck = std::max(conc[k], 0.0); // Ignore negative concentrations
620  m_y[k] = ck;
621  sum += ck * m_molwts[k];
622  norm += ck;
623  }
624  m_mmw = sum/norm;
625  setDensity(sum);
626  doublereal rsum = 1.0/sum;
627  for (size_t k = 0; k != m_kk; ++k) {
628  m_ym[k] = m_y[k] * rsum;
629  m_y[k] = m_ym[k] * m_molwts[k]; // m_y is now the mass fraction
630  }
631  m_stateNum++;
632 }
633 
634 doublereal Phase::elementalMassFraction(const size_t m) const
635 {
637  doublereal Z_m = 0.0;
638  for (size_t k = 0; k != m_kk; ++k) {
639  Z_m += nAtoms(k, m) * atomicWeight(m) / molecularWeight(k)
640  * massFraction(k);
641  }
642  return Z_m;
643 }
644 
645 doublereal Phase::elementalMoleFraction(const size_t m) const
646 {
648  double denom = 0;
649  for (size_t k = 0; k < m_kk; k++) {
650  double atoms = 0;
651  for (size_t j = 0; j < nElements(); j++) {
652  atoms += nAtoms(k, j);
653  }
654  denom += atoms * moleFraction(k);
655  }
656  doublereal numerator = 0.0;
657  for (size_t k = 0; k != m_kk; ++k) {
658  numerator += nAtoms(k, m) * moleFraction(k);
659  }
660  return numerator / denom;
661 }
662 
663 doublereal Phase::molarDensity() const
664 {
665  return density()/meanMolecularWeight();
666 }
667 
668 void Phase::setMolarDensity(const doublereal molar_density)
669 {
670  m_dens = molar_density*meanMolecularWeight();
671 }
672 
673 doublereal Phase::molarVolume() const
674 {
675  return 1.0/molarDensity();
676 }
677 
678 doublereal Phase::chargeDensity() const
679 {
680  doublereal cdens = 0.0;
681  for (size_t k = 0; k < m_kk; k++) {
682  cdens += charge(k)*moleFraction(k);
683  }
684  return cdens * Faraday;
685 }
686 
687 doublereal Phase::mean_X(const doublereal* const Q) const
688 {
689  return m_mmw*std::inner_product(m_ym.begin(), m_ym.end(), Q, 0.0);
690 }
691 
692 doublereal Phase::mean_X(const vector_fp& Q) const
693 {
694  return m_mmw*std::inner_product(m_ym.begin(), m_ym.end(), Q.begin(), 0.0);
695 }
696 
697 doublereal Phase::mean_Y(const doublereal* const Q) const
698 {
699  warn_deprecated("Phase::mean_Y", "To be removed after Cantera 2.2.");
700  return dot(m_y.begin(), m_y.end(), Q);
701 }
702 
703 doublereal Phase::sum_xlogx() const
704 {
705  return m_mmw* Cantera::sum_xlogx(m_ym.begin(), m_ym.end()) + log(m_mmw);
706 }
707 
708 doublereal Phase::sum_xlogQ(doublereal* Q) const
709 {
710  warn_deprecated("Phase::sum_xlogQ", "To be removed after Cantera 2.2.");
711  return m_mmw * Cantera::sum_xlogQ(m_ym.begin(), m_ym.end(), Q);
712 }
713 
714 size_t Phase::addElement(const std::string& symbol, doublereal weight,
715  int atomic_number, doublereal entropy298,
716  int elem_type)
717 {
718  // Look up the atomic weight if not given
719  if (weight == -12345.0) {
720  weight = LookupWtElements(symbol);
721  if (weight < 0.0) {
722  throw CanteraError("Phase::addElement",
723  "No atomic weight found for element: " + symbol);
724  }
725  }
726 
727  // Check for duplicates
728  vector<string>::const_iterator iter = find(m_elementNames.begin(),
729  m_elementNames.end(),
730  symbol);
731  if (iter != m_elementNames.end()) {
732  size_t m = iter - m_elementNames.begin();
733  if (m_atomicWeights[m] != weight) {
734  throw CanteraError("Phase::addElement",
735  "Duplicate elements (" + symbol + ") have different weights");
736  } else {
737  // Ignore attempt to add duplicate element with the same weight
738  return m;
739  }
740  }
741 
742  // Add the new element
743  m_atomicWeights.push_back(weight);
744  m_elementNames.push_back(symbol);
745  m_atomicNumbers.push_back(atomic_number);
746  m_entropy298.push_back(entropy298);
747  if (symbol == "E") {
749  } else {
750  m_elem_type.push_back(elem_type);
751  }
752 
753  m_mm++;
754 
755  // Update species compositions
756  if (m_kk) {
758  m_speciesComp.resize(m_kk*m_mm, 0.0);
759  for (size_t k = 0; k < m_kk; k++) {
760  size_t m_old = m_mm - 1;
761  for (size_t m = 0; m < m_old; m++) {
762  m_speciesComp[k * m_mm + m] = old[k * (m_old) + m];
763  }
764  m_speciesComp[k * (m_mm) + (m_mm-1)] = 0.0;
765  }
766  }
767 
768  return m_mm-1;
769 }
770 
772 {
773  warn_deprecated("Phase::addElement(XML_Node&)",
774  "To be removed after Cantera 2.2.");
775  doublereal weight = 0.0;
776  if (e.hasAttrib("atomicWt")) {
777  weight = fpValue(stripws(e["atomicWt"]));
778  }
779  int anum = 0;
780  if (e.hasAttrib("atomicNumber")) {
781  anum = atoi(stripws(e["atomicNumber"]).c_str());
782  }
783  string symbol = e["name"];
784  doublereal entropy298 = ENTROPY298_UNKNOWN;
785  if (e.hasChild("entropy298")) {
786  XML_Node& e298Node = e.child("entropy298");
787  if (e298Node.hasAttrib("value")) {
788  entropy298 = fpValueCheck(stripws(e298Node["value"]));
789  }
790  }
791  if (weight != 0.0) {
792  addElement(symbol, weight, anum, entropy298);
793  } else {
794  addElement(symbol);
795  }
796 }
797 
798 void Phase::addUniqueElement(const std::string& symbol, doublereal weight,
799  int atomic_number, doublereal entropy298,
800  int elem_type)
801 {
802  warn_deprecated("Phase::addUniqueElement",
803  "Equivalent to Phase::addElement. "
804  "To be removed after Cantera 2.2.");
805  addElement(symbol, weight, atomic_number, entropy298, elem_type);
806 }
807 
809 {
810  warn_deprecated("Phase::addUniqueElement",
811  "To be removed after Cantera 2.2.");
812  addElement(e);
813 }
814 
816 {
817  warn_deprecated("Phase::addElementsFromXML",
818  "Use 'addElements' function. "
819  "To be removed after Cantera 2.2.");
820  installElements(*this, phase);
821 }
822 
824 {
825  warn_deprecated("Phase::freezeElements", "To be removed after Cantera 2.2.");
826 }
827 
829 {
830  warn_deprecated("Phase::elementsFrozen", "To be removed after Cantera 2.2.");
831  return false;
832 }
833 
834 size_t Phase::addUniqueElementAfterFreeze(const std::string& symbol,
835  doublereal weight, int atomicNumber,
836  doublereal entropy298, int elem_type)
837 {
838  warn_deprecated("Phase::addUniqueElementAfterFreeze",
839  "Equivalent to Phase::addElement. "
840  "To be removed after Cantera 2.2");
841  return addElement(symbol, weight, atomicNumber, entropy298, elem_type);
842 }
843 
844 bool Phase::addSpecies(shared_ptr<Species> spec) {
845  m_species[spec->name] = spec;
846  vector_fp comp(nElements());
847  for (map<string, double>::const_iterator iter = spec->composition.begin();
848  iter != spec->composition.end();
849  iter++) {
850  size_t m = elementIndex(iter->first);
851  if (m == npos) { // Element doesn't exist in this phase
852  switch (m_undefinedElementBehavior) {
853  case UndefElement::ignore:
854  return false;
855 
856  case UndefElement::add:
857  addElement(iter->first);
858  comp.resize(nElements());
859  m = elementIndex(iter->first);
860  break;
861 
862  case UndefElement::error:
863  default:
864  throw CanteraError("Phase::addSpecies",
865  "Species '" + spec->name + "' contains an "
866  "undefined element '" + iter->first + "'.");
867  }
868  }
869  comp[m] = iter->second;
870  }
871 
872  m_speciesNames.push_back(spec->name);
873  m_speciesIndices[spec->name] = m_kk;
874  m_speciesCharge.push_back(spec->charge);
875  m_speciesSize.push_back(spec->size);
876  size_t ne = nElements();
877 
878  double wt = 0.0;
879  const vector_fp& aw = atomicWeights();
880  if (spec->charge != 0.0) {
881  size_t eindex = elementIndex("E");
882  if (eindex != npos) {
883  doublereal ecomp = comp[eindex];
884  if (fabs(spec->charge + ecomp) > 0.001) {
885  if (ecomp != 0.0) {
886  throw CanteraError("Phase::addSpecies",
887  "Input charge and element E compositions differ "
888  "for species " + spec->name);
889  } else {
890  // Just fix up the element E composition based on the input
891  // species charge
892  comp[eindex] = -spec->charge;
893  }
894  }
895  } else {
896  addElement("E", 0.000545, 0, 0.0, CT_ELEM_TYPE_ELECTRONCHARGE);
897  ne = nElements();
898  eindex = elementIndex("E");
899  comp.resize(ne);
900  comp[ne - 1] = - spec->charge;
901  }
902  }
903  for (size_t m = 0; m < ne; m++) {
904  m_speciesComp.push_back(comp[m]);
905  wt += comp[m] * aw[m];
906  }
907 
908  // Some surface phases may define species representing empty sites
909  // that have zero molecular weight. Give them a very small molecular
910  // weight to avoid dividing by zero.
911  wt = std::max(wt, Tiny);
912  m_molwts.push_back(wt);
913  m_rmolwts.push_back(1.0/wt);
914  m_kk++;
915 
916  // Ensure that the Phase has a valid mass fraction vector that sums to
917  // one. We will assume that species 0 has a mass fraction of 1.0 and mass
918  // fraction of all other species is 0.0.
919  if (m_kk == 1) {
920  m_y.push_back(1.0);
921  m_ym.push_back(m_rmolwts[0]);
922  m_mmw = 1.0 / m_ym[0];
923  } else {
924  m_y.push_back(0.0);
925  m_ym.push_back(0.0);
926  }
927  return true;
928 }
929 
930 void Phase::addSpecies(const std::string& name_, const doublereal* comp,
931  doublereal charge_, doublereal size_)
932 {
933  warn_deprecated("Phase::addSpecies(string, double*, double, double)",
934  "Use AddSpecies(shared_ptr<Species> spec) instead. To be removed "
935  "after Cantera 2.2.");
936  compositionMap cmap;
937  for (size_t i = 0; i < nElements(); i++) {
938  if (comp[i]) {
939  cmap[elementName(i)] = comp[i];
940  }
941  }
942  shared_ptr<Species> sp(new Species(name_, cmap, charge_, size_));
943  Phase::addSpecies(sp);
944 }
945 
946 void Phase::addUniqueSpecies(const std::string& name_, const doublereal* comp,
947  doublereal charge_, doublereal size_)
948 {
949  warn_deprecated("Phase::addUniqueSpecies",
950  "Use AddSpecies(shared_ptr<Species> spec) instead. To be removed "
951  "after Cantera 2.2.");
952  for (size_t k = 0; k < m_kk; k++) {
953  if (m_speciesNames[k] == name_) {
954  // We have found a match. Do some compatibility checks.
955  for (size_t i = 0; i < m_mm; i++) {
956  if (comp[i] != m_speciesComp[k * m_mm + i]) {
957  throw CanteraError("addUniqueSpecies",
958  "Duplicate species have different "
959  "compositions: " + name_);
960  }
961  }
962  if (charge_ != m_speciesCharge[k]) {
963  throw CanteraError("addUniqueSpecies",
964  "Duplicate species have different "
965  "charges: " + name_);
966  }
967  if (size_ != m_speciesSize[k]) {
968  throw CanteraError("addUniqueSpecies",
969  "Duplicate species have different "
970  "sizes: " + name_);
971  }
972  return;
973  }
974  }
975  addSpecies(name_, comp, charge_, size_);
976 }
977 
978 shared_ptr<Species> Phase::species(const std::string& name) const
979 {
980  return getValue(m_species, name);
981 }
982 
983 shared_ptr<Species> Phase::species(size_t k) const
984 {
985  return species(m_speciesNames[k]);
986 }
987 
989  m_undefinedElementBehavior = UndefElement::ignore;
990 }
991 
993  m_undefinedElementBehavior = UndefElement::add;
994 }
995 
998 }
999 
1000 bool Phase::ready() const
1001 {
1002  return (m_kk > 0);
1003 }
1004 
1005 } // namespace Cantera
Phase()
Default constructor.
Definition: Phase.cpp:19
std::map< std::string, doublereal > compositionMap
Map connecting a string name with a double.
Definition: ct_defs.h:149
doublereal fpValue(const std::string &val)
Translate a string into one doublereal value.
doublereal nAtoms(size_t k, size_t m) const
Number of atoms of element m in species k.
Definition: Phase.cpp:243
virtual void setMoleFractions_NoNorm(const doublereal *const x)
Set the mole fractions to the specified values without normalizing.
Definition: Phase.cpp:367
doublereal molecularWeight(size_t k) const
Molecular weight of species k.
Definition: Phase.cpp:494
vector_fp m_y
Mass fractions of the species.
Definition: Phase.h:895
void setState_RY(doublereal rho, doublereal *y)
Set the density (kg/m^3) and mass fractions.
Definition: Phase.cpp:488
Array size error.
Definition: ctexceptions.h:154
std::vector< std::string > m_elementNames
element names
Definition: Phase.h:914
virtual doublereal density() const
Density (kg/m^3).
Definition: Phase.h:608
doublereal LookupWtElements(const std::string &ename)
Function to look up an atomic weight This function looks up the argument string in the database above...
Definition: Elements.cpp:171
void restoreState(const vector_fp &state)
Restore a state saved on a previous call to saveState.
Definition: Phase.cpp:314
CTML ("Cantera Markup Language") is the variant of XML that Cantera uses to store data...
void setState_TRY(doublereal t, doublereal dens, const doublereal *y)
Set the internally stored temperature (K), density, and mass fractions.
Definition: Phase.cpp:450
XML_Node * findXMLPhase(XML_Node *root, const std::string &idtarget)
Search an XML_Node tree for a named phase XML_Node.
Definition: xml.cpp:1108
size_t nElements() const
Number of elements.
Definition: Phase.cpp:167
vector_fp m_atomicWeights
element atomic weights (kg kmol-1)
Definition: Phase.h:912
void getMassFractions(doublereal *const y) const
Get the species mass fractions.
Definition: Phase.cpp:598
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:165
vector_fp m_speciesCharge
Vector of species charges. length m_kk.
Definition: Phase.h:858
Header file for class Phase.
Headers for the factory class that can create known ThermoPhase objects (see Thermodynamic Properties...
vector_fp m_entropy298
Entropy at 298.15 K and 1 bar of stable state pure elements (J kmol-1)
Definition: Phase.h:918
doublereal atomicWeight(size_t m) const
Atomic weight of element m.
Definition: Phase.cpp:207
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:100
std::map< std::string, size_t > m_speciesIndices
Map of species names to indices.
Definition: Phase.h:909
void warn_deprecated(const std::string &method, const std::string &extra)
Print a warning indicating that method is deprecated.
Definition: global.cpp:78
vector_fp m_speciesSize
Vector of species sizes.
Definition: Phase.h:856
doublereal m_mmw
mean molecular weight of the mixture (kg kmol-1)
Definition: Phase.h:884
Class Phase is the base class for phases of matter, managing the species and elements in a phase...
Definition: Phase.h:92
#define CT_ELEM_TYPE_ELECTRONCHARGE
This refers to conservation of electrons.
Definition: Elements.h:41
doublereal molarDensity() const
Molar density (kmol/m^3).
Definition: Phase.cpp:663
void getMoleFractionsByName(compositionMap &x) const
Get the mole fractions by name.
Definition: Phase.cpp:520
Unary operator to multiply the argument by a constant.
Definition: utilities.h:32
void getMoleFractions(doublereal *const x) const
Get the species mole fraction vector.
Definition: Phase.cpp:556
void checkElementIndex(size_t m) const
Check that the specified element index is in range Throws an exception if m is greater than nElements...
Definition: Phase.cpp:172
void getConcentrations(doublereal *const c) const
Get the species concentrations (kmol/m^3).
Definition: Phase.cpp:609
std::string name() const
Return the name of the phase.
Definition: Phase.cpp:157
UndefElement::behavior m_undefinedElementBehavior
Flag determining behavior when adding species with an undefined element.
Definition: Phase.h:863
std::string m_name
Name of the phase.
Definition: Phase.h:875
void checkElementArraySize(size_t mm) const
Check that an array size is at least nElements() Throws an exception if mm is less than nElements()...
Definition: Phase.cpp:179
shared_ptr< Species > species(const std::string &name) const
Return the Species object for the named species.
Definition: Phase.cpp:978
doublereal concentration(const size_t k) const
Concentration of species k.
Definition: Phase.cpp:603
#define AssertThrowMsg(expr, procedure, message)
Assertion must be true or an error is thrown.
Definition: ctexceptions.h:301
doublereal sum_xlogQ(doublereal *const Q) const
Evaluate .
Definition: Phase.cpp:708
XML_Node & child(const size_t n) const
Return a changeable reference to the n'th child of the current node.
Definition: xml.cpp:573
doublereal entropyElement298(size_t m) const
Entropy of the element in its standard state at 298 K and 1 bar.
Definition: Phase.cpp:212
void checkSpeciesIndex(size_t k) const
Check that the specified species index is in range Throws an exception if k is greater than nSpecies(...
Definition: Phase.cpp:283
void setName(const std::string &nm)
Sets the string name for the phase.
Definition: Phase.cpp:162
doublereal mean_X(const doublereal *const Q) const
Evaluate the mole-fraction-weighted mean of an array Q.
Definition: Phase.cpp:687
const vector_fp & atomicWeights() const
Return a read-only reference to the vector of atomic weights.
Definition: Phase.cpp:221
virtual bool ready() const
Returns a bool indicating whether the object is ready for use.
Definition: Phase.cpp:1000
void throwUndefinedElements()
Set the behavior when adding a species containing undefined elements to throw an exception.
Definition: Phase.cpp:996
int m_stateNum
State Change variable.
Definition: Phase.h:903
size_t m_ndim
Dimensionality of the phase.
Definition: Phase.h:847
size_t speciesIndex(const std::string &name) const
Returns the index of a species named 'name' within the Phase object.
Definition: Phase.cpp:257
void ignoreUndefinedElements()
Set behavior when adding a species containing undefined elements to just skip the species...
Definition: Phase.cpp:988
std::vector< std::string > m_speciesNames
Vector of the species names.
Definition: Phase.h:906
void setState_TRX(doublereal t, doublereal dens, const doublereal *x)
Set the internally stored temperature (K), density, and mole fractions.
Definition: Phase.cpp:429
void getAtoms(size_t k, double *atomArray) const
Get a vector containing the atomic composition of species k.
Definition: Phase.cpp:250
bool elementsFrozen()
True if freezeElements has been called.
Definition: Phase.cpp:828
std::string stripws(const std::string &s)
Strip the leading and trailing white space from a string.
void addUniqueElement(const std::string &symbol, doublereal weight=-12345.0, int atomicNumber=0, doublereal entropy298=ENTROPY298_UNKNOWN, int elem_type=CT_ELEM_TYPE_ABSPOS)
Add an element, checking for uniqueness The uniqueness is checked by comparing the string symbol...
Definition: Phase.cpp:798
doublereal molarVolume() const
Molar volume (m^3/kmol).
Definition: Phase.cpp:673
doublereal sum_xlogx() const
Evaluate .
Definition: Phase.cpp:703
enum CT_RealNumber_Range_Behavior realNumberRangeBehavior_
Overflow behavior of real number calculations involving this thermo object.
Definition: Phase.h:927
int atomicNumber(size_t m) const
Atomic number of element m.
Definition: Phase.cpp:226
void error(const std::string &msg)
Write an error message and quit.
Definition: global.cpp:72
doublereal chargeDensity() const
Charge density [C/m^3].
Definition: Phase.cpp:678
const doublereal * massFractions() const
Return a const pointer to the mass fraction array.
Definition: Phase.h:482
void setMoleFractionsByName(const compositionMap &xMap)
Set the species mole fractions by name.
Definition: Phase.cpp:376
std::string id() const
Return the string id for the phase.
Definition: Phase.cpp:147
void setMassFractionsByName(const compositionMap &yMap)
Set the species mass fractions by name.
Definition: Phase.cpp:415
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:99
doublereal sum_xlogQ(InputIter1 begin, InputIter1 end, InputIter2 Q_begin)
Compute .
Definition: utilities.h:564
void setState_TNX(doublereal t, doublereal n, const doublereal *x)
Set the internally stored temperature (K), molar density (kmol/m^3), and mole fractions.
Definition: Phase.cpp:436
void addElementsFromXML(const XML_Node &phase)
Add all elements referenced in an XML_Node tree.
Definition: Phase.cpp:815
virtual void setConcentrations(const doublereal *const conc)
Set the concentrations to the specified values within the phase.
Definition: Phase.cpp:614
const U & getValue(const std::map< T, U > &m, const T &key)
Const accessor for a value in a std::map.
Definition: utilities.h:714
virtual void setMoleFractions(const doublereal *const x)
Set the mole fractions to the specified values There is no restriction on the sum of the mole fractio...
Definition: Phase.cpp:331
virtual ~Phase()
Destructor.
Definition: Phase.cpp:114
std::string parseSpeciesName(const std::string &nameStr, std::string &phaseName)
Parse a name string, separating out the phase name from the species name.
bool hasChild(const std::string &ch) const
Tests whether the current node has a child node with a particular name.
Definition: xml.cpp:563
doublereal sum_xlogx(InputIter begin, InputIter end)
Compute .
Definition: utilities.h:536
const std::vector< std::string > & elementNames() const
Return a read-only reference to the vector of element names.
Definition: Phase.cpp:202
doublereal massFraction(size_t k) const
Return the mass fraction of a single species.
Definition: Phase.cpp:582
virtual bool addSpecies(shared_ptr< Species > spec)
Add a Species to this Phase.
Definition: Phase.cpp:844
doublereal elementalMoleFraction(const size_t m) const
Elemental mole fraction of element m.
Definition: Phase.cpp:645
virtual void setMolarDensity(const doublereal molarDensity)
Set the internally stored molar density (kmol/m^3) of the phase.
Definition: Phase.cpp:668
void installElements(Phase &th, const XML_Node &phaseNode)
Add the elements given in an XML_Node tree to the specified phase.
doublereal dot(InputIter x_begin, InputIter x_end, InputIter2 y_begin)
Function that calculates a templated inner product.
Definition: utilities.h:135
#define ENTROPY298_UNKNOWN
Number indicating we don't know the entropy of the element in its most stable state at 298...
Definition: Elements.h:84
virtual void setMassFractions_NoNorm(const doublereal *const y)
Set the mass fractions to the specified values without normalizing.
Definition: Phase.cpp:404
size_t nSpecies() const
Returns the number of species in the phase.
Definition: Phase.h:265
void setState_TX(doublereal t, doublereal *x)
Set the internally stored temperature (K) and mole fractions.
Definition: Phase.cpp:470
vector_int m_elem_type
Vector of element types.
Definition: Phase.h:915
compositionMap parseCompString(const std::string &ss, const std::vector< std::string > &names)
Parse a composition string into a map consisting of individual key:composition pairs.
const std::vector< std::string > & speciesNames() const
Return a const reference to the vector of species names.
Definition: Phase.cpp:278
doublereal moleFraction(size_t k) const
Return the mole fraction of a single species.
Definition: Phase.cpp:561
const vector_fp & molecularWeights() const
Return a const reference to the internal vector of molecular weights.
Definition: Phase.cpp:515
#define AssertTrace(expr)
Assertion must be true or an error is thrown.
Definition: ctexceptions.h:270
doublereal temperature() const
Temperature (K).
Definition: Phase.h:602
void freezeElements()
Prohibit addition of more elements, and prepare to add species.
Definition: Phase.cpp:823
size_t addElement(const std::string &symbol, doublereal weight=-12345.0, int atomicNumber=0, doublereal entropy298=ENTROPY298_UNKNOWN, int elem_type=CT_ELEM_TYPE_ABSPOS)
Add an element.
Definition: Phase.cpp:714
std::string id() const
Return the id attribute, if present.
Definition: xml.cpp:448
vector_fp m_molwts
species molecular weights (kg kmol-1)
Definition: Phase.h:897
void setState_TY(doublereal t, doublereal *y)
Set the internally stored temperature (K) and mass fractions.
Definition: Phase.cpp:476
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
Definition: ct_defs.h:157
void checkSpeciesArraySize(size_t kk) const
Check that an array size is at least nSpecies() Throws an exception if kk is less than nSpecies()...
Definition: Phase.cpp:290
XML_Node & xml() const
Returns a const reference to the XML_Node that describes the phase.
Definition: Phase.cpp:123
size_t elementIndex(const std::string &name) const
Return the index of element named 'name'.
Definition: Phase.cpp:192
Templates for operations on vector-like objects.
Phase & operator=(const Phase &right)
Assignment operator.
Definition: Phase.cpp:53
void addUndefinedElements()
Set behavior when adding a species containing undefined elements to add those elements to the phase...
Definition: Phase.cpp:992
size_t m_mm
Number of elements.
Definition: Phase.h:911
virtual void setTemperature(const doublereal temp)
Set the internally stored temperature of the phase (K).
Definition: Phase.h:638
void scale(InputIter begin, InputIter end, OutputIter out, S scale_factor)
Multiply elements of an array by a scale factor.
Definition: utilities.h:158
const doublereal Tiny
Small number to compare differences of mole fractions against.
Definition: ct_defs.h:142
compositionMap getMassFractionsByName(double threshold=0.0) const
Get the mass fractions by name.
Definition: Phase.cpp:544
std::string m_id
ID of the phase.
Definition: Phase.h:870
doublereal m_dens
Density (kg m-3).
Definition: Phase.h:882
vector_fp m_ym
m_ym[k] = mole fraction of species k divided by the mean molecular weight of mixture.
Definition: Phase.h:888
doublereal meanMolecularWeight() const
The mean molecular weight. Units: (kg/kmol)
Definition: Phase.h:669
XML_Node * m_xml
XML node containing the XML info for this phase.
Definition: Phase.h:866
vector_int m_atomicNumbers
element atomic numbers
Definition: Phase.h:913
Contains declarations for string manipulation functions within Cantera.
std::string speciesSPName(int k) const
Returns the expanded species name of a species, including the phase name This is guaranteed to be uni...
Definition: Phase.cpp:297
void getMolecularWeights(vector_fp &weights) const
Copy the vector of molecular weights into vector weights.
Definition: Phase.cpp:500
std::string elementName(size_t m) const
Name of the element with index m.
Definition: Phase.cpp:186
doublereal m_temp
Temperature (K). This is an independent variable.
Definition: Phase.h:877
void saveState(vector_fp &state) const
Save the current internal state of the phase Write to vector 'state' the current internal state...
Definition: Phase.cpp:302
virtual void setMassFractions(const doublereal *const y)
Set the mass fractions to the specified values and normalize them.
Definition: Phase.cpp:390
int elementType(size_t m) const
Return the element constraint type Possible types include:
Definition: Phase.cpp:231
Contains data about a single chemical species.
Definition: Species.h:21
vector_fp m_rmolwts
inverse of species molecular weights (kmol kg-1)
Definition: Phase.h:899
vector_fp m_speciesComp
Atomic composition of the species.
Definition: Phase.h:852
void setXMLdata(XML_Node &xmlPhase)
Stores the XML tree information for the current phase.
Definition: Phase.cpp:128
void setState_RX(doublereal rho, doublereal *x)
Set the density (kg/m^3) and mole fractions.
Definition: Phase.cpp:482
size_t m_kk
Number of species in the phase.
Definition: Phase.h:843
size_t addUniqueElementAfterFreeze(const std::string &symbol, doublereal weight, int atomicNumber, doublereal entropy298=ENTROPY298_UNKNOWN, int elem_type=CT_ELEM_TYPE_ABSPOS)
Add an element after elements have been frozen, checking for uniqueness The uniqueness is checked by ...
Definition: Phase.cpp:834
An array index is out of range.
Definition: ctexceptions.h:184
int changeElementType(int m, int elem_type)
Change the element type of the mth constraint Reassigns an element type.
Definition: Phase.cpp:236
void setID(const std::string &id)
Set the string id for the phase.
Definition: Phase.cpp:152
Cantera will throw an error in debug mode but will not in production mode.
Definition: ctexceptions.h:86
XML_Node & root() const
Return the root of the current XML_Node tree.
Definition: xml.cpp:1095
doublereal fpValueCheck(const std::string &val)
Translate a string into one doublereal value, with error checking.
void setState_TR(doublereal t, doublereal rho)
Set the internally stored temperature (K) and density (kg/m^3)
Definition: Phase.cpp:464
std::string speciesName(size_t k) const
Name of the species with index k.
Definition: Phase.cpp:272
void addUniqueSpecies(const std::string &name, const doublereal *comp, doublereal charge=0.0, doublereal size=1.0)
Add a species to the phase, checking for uniqueness of the name This routine checks for uniqueness of...
Definition: Phase.cpp:946
const doublereal * moleFractdivMMW() const
Returns a const pointer to the start of the moleFraction/MW array.
Definition: Phase.cpp:577
virtual void setDensity(const doublereal density_)
Set the internally stored density (kg/m^3) of the phase Note the density of a phase is an independent...
Definition: Phase.h:623
doublereal mean_Y(const doublereal *const Q) const
Evaluate the mass-fraction-weighted mean of an array Q.
Definition: Phase.cpp:697
bool hasAttrib(const std::string &a) const
Tests whether the current node has an attribute with a particular name.
Definition: xml.cpp:568
doublereal charge(size_t k) const
Dimensionless electrical charge of a single molecule of species k The charge is normalized by the the...
Definition: Phase.h:578
doublereal elementalMassFraction(const size_t m) const
Elemental mass fraction of element m.
Definition: Phase.cpp:634