Cantera  2.3.0
Phase.cpp
Go to the documentation of this file.
1 /**
2  * @file Phase.cpp
3  * Definition file for class Phase.
4  */
5 
6 // This file is part of Cantera. See License.txt in the top-level directory or
7 // at http://www.cantera.org/license.txt for license and copyright information.
8 
9 #include "cantera/thermo/Phase.h"
10 #include "cantera/base/utilities.h"
12 #include "cantera/base/ctml.h"
14 
15 using namespace std;
16 
17 namespace Cantera
18 {
19 
20 Phase::Phase() :
21  m_kk(0),
22  m_ndim(3),
23  m_undefinedElementBehavior(UndefElement::error),
24  m_xml(new XML_Node("phase")),
25  m_id("<phase>"),
26  m_temp(0.001),
27  m_dens(0.001),
28  m_mmw(0.0),
29  m_stateNum(-1),
30  m_mm(0),
31  m_elem_type(0)
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 {
48  // Use the assignment operator to do the actual copying
49  operator=(right);
50 }
51 
52 Phase& Phase::operator=(const Phase& right)
53 {
54  // Check for self assignment.
55  if (this == &right) {
56  return *this;
57  }
58 
59  // Handle our own data
60  m_kk = right.m_kk;
61  m_ndim = right.m_ndim;
62  m_undefinedElementBehavior = right.m_undefinedElementBehavior;
63  m_temp = right.m_temp;
64  m_dens = right.m_dens;
65  m_mmw = right.m_mmw;
66  m_ym = right.m_ym;
67  m_y = right.m_y;
68  m_molwts = right.m_molwts;
69  m_rmolwts = right.m_rmolwts;
70  m_stateNum = -1;
71 
72  m_speciesNames = right.m_speciesNames;
73  m_speciesComp = right.m_speciesComp;
74  m_speciesCharge = right.m_speciesCharge;
75  m_speciesSize = right.m_speciesSize;
76  m_mm = right.m_mm;
77  m_atomicWeights = right.m_atomicWeights;
78  m_atomicNumbers = right.m_atomicNumbers;
79  m_elementNames = right.m_elementNames;
80  m_entropy298 = right.m_entropy298;
81  m_elem_type = right.m_elem_type;
82 
83  // This is a little complicated. -> Because we delete m_xml in the
84  // destructor, we own m_xml completely, and we need to have our own
85  // individual copies of the XML data tree in each object
86  if (m_xml) {
87  XML_Node* rroot = &m_xml->root();
88  delete rroot;
89  m_xml = 0;
90  }
91  if (right.m_xml) {
92  XML_Node *rroot = &right.m_xml->root();
93  XML_Node *root_xml = new XML_Node();
94  rroot->copy(root_xml);
95  m_xml = findXMLPhase(root_xml, right.m_xml->id());
96  if (!m_xml) {
97  throw CanteraError("Phase::operator=()", "Confused: Couldn't find original phase " + right.m_xml->id());
98  }
99  if (&m_xml->root() != root_xml) {
100  throw CanteraError("Phase::operator=()", "confused: root changed");
101  }
102  }
103  m_id = right.m_id;
104  m_name = right.m_name;
105  return *this;
106 }
107 
108 Phase::~Phase()
109 {
110  if (m_xml) {
111  XML_Node* xroot = &m_xml->root();
112  delete xroot;
113  }
114  m_xml = 0;
115 }
116 
118 {
119  return *m_xml;
120 }
121 
123 {
124  XML_Node* xroot = &xmlPhase.root();
125  XML_Node *root_xml = new XML_Node();
126  xroot->copy(root_xml);
127  if (m_xml) {
128  XML_Node *rOld = &m_xml->root();
129  delete rOld;
130  m_xml = 0;
131  }
132  m_xml = findXMLPhase(root_xml, xmlPhase.id());
133  if (!m_xml) {
134  throw CanteraError("Phase::setXMLdata()", "XML 'phase' node not found");
135  }
136  if (&m_xml->root() != root_xml) {
137  throw CanteraError("Phase::setXMLdata()", "Root XML node not found");
138  }
139 }
140 
141 std::string Phase::id() const
142 {
143  return m_id;
144 }
145 
146 void Phase::setID(const std::string& id_)
147 {
148  m_id = id_;
149 }
150 
151 std::string Phase::name() const
152 {
153  return m_name;
154 }
155 
156 void Phase::setName(const std::string& nm)
157 {
158  m_name = nm;
159 }
160 
161 size_t Phase::nElements() const
162 {
163  return m_mm;
164 }
165 
166 void Phase::checkElementIndex(size_t m) const
167 {
168  if (m >= m_mm) {
169  throw IndexError("checkElementIndex", "elements", m, m_mm-1);
170  }
171 }
172 
173 void Phase::checkElementArraySize(size_t mm) const
174 {
175  if (m_mm > mm) {
176  throw ArraySizeError("checkElementArraySize", mm, m_mm);
177  }
178 }
179 
180 string Phase::elementName(size_t m) const
181 {
183  return m_elementNames[m];
184 }
185 
186 size_t Phase::elementIndex(const std::string& elementName) const
187 {
188  for (size_t i = 0; i < m_mm; i++) {
189  if (m_elementNames[i] == elementName) {
190  return i;
191  }
192  }
193  return npos;
194 }
195 
196 const vector<string>& Phase::elementNames() const
197 {
198  return m_elementNames;
199 }
200 
201 doublereal Phase::atomicWeight(size_t m) const
202 {
203  return m_atomicWeights[m];
204 }
205 
206 doublereal Phase::entropyElement298(size_t m) const
207 {
209  "Elements::entropy298",
210  "Entropy at 298 K of element is unknown");
211  AssertTrace(m < m_mm);
212  return m_entropy298[m];
213 }
214 
216 {
217  return m_atomicWeights;
218 }
219 
220 int Phase::atomicNumber(size_t m) const
221 {
222  return m_atomicNumbers[m];
223 }
224 
225 int Phase::elementType(size_t m) const
226 {
227  return m_elem_type[m];
228 }
229 
230 int Phase::changeElementType(int m, int elem_type)
231 {
232  int old = m_elem_type[m];
233  m_elem_type[m] = elem_type;
234  return old;
235 }
236 
237 doublereal Phase::nAtoms(size_t k, size_t m) const
238 {
241  return m_speciesComp[m_mm * k + m];
242 }
243 
244 void Phase::getAtoms(size_t k, double* atomArray) const
245 {
246  for (size_t m = 0; m < m_mm; m++) {
247  atomArray[m] = (double) m_speciesComp[m_mm * k + m];
248  }
249 }
250 
251 size_t Phase::speciesIndex(const std::string& nameStr) const
252 {
253  size_t loc = getValue(m_speciesIndices, ba::to_lower_copy(nameStr), npos);
254  if (loc == npos && nameStr.find(':') != npos) {
255  std::string pn;
256  std::string sn = ba::to_lower_copy(parseSpeciesName(nameStr, pn));
257  if (pn == "" || pn == m_name || pn == m_id) {
258  return getValue(m_speciesIndices, sn, npos);
259  } else {
260  return npos;
261  }
262  } else {
263  return loc;
264  }
265 }
266 
267 string Phase::speciesName(size_t k) const
268 {
270  return m_speciesNames[k];
271 }
272 
273 const vector<string>& Phase::speciesNames() const
274 {
275  return m_speciesNames;
276 }
277 
278 void Phase::checkSpeciesIndex(size_t k) const
279 {
280  if (k >= m_kk) {
281  throw IndexError("checkSpeciesIndex", "species", k, m_kk-1);
282  }
283 }
284 
285 void Phase::checkSpeciesArraySize(size_t kk) const
286 {
287  if (m_kk > kk) {
288  throw ArraySizeError("checkSpeciesArraySize", kk, m_kk);
289  }
290 }
291 
292 std::string Phase::speciesSPName(int k) const
293 {
294  return m_name + ":" + speciesName(k);
295 }
296 
297 void Phase::saveState(vector_fp& state) const
298 {
299  state.resize(nSpecies() + 2);
300  saveState(state.size(), &state[0]);
301 }
302 void Phase::saveState(size_t lenstate, doublereal* state) const
303 {
304  state[0] = temperature();
305  state[1] = density();
306  getMassFractions(state + 2);
307 }
308 
309 void Phase::restoreState(const vector_fp& state)
310 {
311  restoreState(state.size(),&state[0]);
313 }
314 
315 void Phase::restoreState(size_t lenstate, const doublereal* state)
316 {
317  if (lenstate >= nSpecies() + 2) {
318  setMassFractions_NoNorm(state + 2);
319  setTemperature(state[0]);
320  setDensity(state[1]);
321  } else {
322  throw ArraySizeError("Phase::restoreState",
323  lenstate,nSpecies()+2);
324  }
325 }
326 
327 void Phase::setMoleFractions(const doublereal* const x)
328 {
329  // Use m_y as a temporary work vector for the non-negative mole fractions
330  doublereal norm = 0.0;
331  // sum is calculated below as the unnormalized molecular weight
332  doublereal sum = 0;
333  for (size_t k = 0; k < m_kk; k++) {
334  double xk = std::max(x[k], 0.0); // Ignore negative mole fractions
335  m_y[k] = xk;
336  norm += xk;
337  sum += m_molwts[k] * xk;
338  }
339 
340  // Set m_ym_ to the normalized mole fractions divided by the normalized mean
341  // molecular weight:
342  // m_ym_k = X_k / (sum_k X_k M_k)
343  const doublereal invSum = 1.0/sum;
344  for (size_t k=0; k < m_kk; k++) {
345  m_ym[k] = m_y[k]*invSum;
346  }
347 
348  // Now set m_y to the normalized mass fractions:
349  // m_y = X_k M_k / (sum_k X_k M_k)
350  for (size_t k=0; k < m_kk; k++) {
351  m_y[k] = m_ym[k] * m_molwts[k];
352  }
353 
354  // Calculate the normalized molecular weight
355  m_mmw = sum/norm;
357 }
358 
359 void Phase::setMoleFractions_NoNorm(const doublereal* const x)
360 {
361  m_mmw = dot(x, x + m_kk, m_molwts.begin());
362  transform(x, x + m_kk, m_ym.begin(), timesConstant<double>(1.0/m_mmw));
363  transform(m_ym.begin(), m_ym.begin() + m_kk, m_molwts.begin(),
364  m_y.begin(), multiplies<double>());
366 }
367 
369 {
370  vector_fp mf(m_kk, 0.0);
371  for (const auto& sp : xMap) {
372  try {
373  mf[m_speciesIndices.at(ba::to_lower_copy(sp.first))] = sp.second;
374  } catch (std::out_of_range&) {
375  throw CanteraError("Phase::setMoleFractionsByName",
376  "Unknown species '{}'", sp.first);
377  }
378  }
379  setMoleFractions(&mf[0]);
380 }
381 
382 void Phase::setMoleFractionsByName(const std::string& x)
383 {
385 }
386 
387 void Phase::setMassFractions(const doublereal* const y)
388 {
389  for (size_t k = 0; k < m_kk; k++) {
390  m_y[k] = std::max(y[k], 0.0); // Ignore negative mass fractions
391  }
392  doublereal norm = accumulate(m_y.begin(), m_y.end(), 0.0);
393  scale(m_y.begin(), m_y.end(), m_y.begin(), 1.0/norm);
394 
395  transform(m_y.begin(), m_y.end(), m_rmolwts.begin(),
396  m_ym.begin(), multiplies<double>());
397  m_mmw = 1.0 / accumulate(m_ym.begin(), m_ym.end(), 0.0);
399 }
400 
401 void Phase::setMassFractions_NoNorm(const doublereal* const y)
402 {
403  doublereal sum = 0.0;
404  copy(y, y + m_kk, m_y.begin());
405  transform(m_y.begin(), m_y.end(), m_rmolwts.begin(), m_ym.begin(),
406  multiplies<double>());
407  sum = accumulate(m_ym.begin(), m_ym.end(), 0.0);
408  m_mmw = 1.0/sum;
410 }
411 
413 {
414  vector_fp mf(m_kk, 0.0);
415  for (const auto& sp : yMap) {
416  try {
417  mf[m_speciesIndices.at(ba::to_lower_copy(sp.first))] = sp.second;
418  } catch (std::out_of_range&) {
419  throw CanteraError("Phase::setMassFractionsByName",
420  "Unknown species '{}'", sp.first);
421  }
422  }
423  setMassFractions(&mf[0]);
424 }
425 
426 void Phase::setMassFractionsByName(const std::string& y)
427 {
429 }
430 
431 void Phase::setState_TRX(doublereal t, doublereal dens, const doublereal* x)
432 {
433  setMoleFractions(x);
434  setTemperature(t);
435  setDensity(dens);
436 }
437 
438 void Phase::setState_TNX(doublereal t, doublereal n, const doublereal* x)
439 {
440  setMoleFractions(x);
441  setTemperature(t);
442  setMolarDensity(n);
443 }
444 
445 void Phase::setState_TRX(doublereal t, doublereal dens, const compositionMap& x)
446 {
448  setTemperature(t);
449  setDensity(dens);
450 }
451 
452 void Phase::setState_TRY(doublereal t, doublereal dens, const doublereal* y)
453 {
454  setMassFractions(y);
455  setTemperature(t);
456  setDensity(dens);
457 }
458 
459 void Phase::setState_TRY(doublereal t, doublereal dens, const compositionMap& y)
460 {
462  setTemperature(t);
463  setDensity(dens);
464 }
465 
466 void Phase::setState_TR(doublereal t, doublereal rho)
467 {
468  setTemperature(t);
469  setDensity(rho);
470 }
471 
472 void Phase::setState_TX(doublereal t, doublereal* x)
473 {
474  setTemperature(t);
475  setMoleFractions(x);
476 }
477 
478 void Phase::setState_TY(doublereal t, doublereal* y)
479 {
480  setTemperature(t);
481  setMassFractions(y);
482 }
483 
484 void Phase::setState_RX(doublereal rho, doublereal* x)
485 {
486  setMoleFractions(x);
487  setDensity(rho);
488 }
489 
490 void Phase::setState_RY(doublereal rho, doublereal* y)
491 {
492  setMassFractions(y);
493  setDensity(rho);
494 }
495 
496 doublereal Phase::molecularWeight(size_t k) const
497 {
499  return m_molwts[k];
500 }
501 
503 {
504  weights = molecularWeights();
505 }
506 
507 void Phase::getMolecularWeights(doublereal* weights) const
508 {
509  const vector_fp& mw = molecularWeights();
510  copy(mw.begin(), mw.end(), weights);
511 }
512 
514 {
515  return m_molwts;
516 }
517 
519 {
520  compositionMap comp;
521  for (size_t k = 0; k < m_kk; k++) {
522  double x = moleFraction(k);
523  if (x > threshold) {
524  comp[speciesName(k)] = x;
525  }
526  }
527  return comp;
528 }
529 
531 {
532  compositionMap comp;
533  for (size_t k = 0; k < m_kk; k++) {
534  double x = massFraction(k);
535  if (x > threshold) {
536  comp[speciesName(k)] = x;
537  }
538  }
539  return comp;
540 }
541 
542 void Phase::getMoleFractions(doublereal* const x) const
543 {
544  scale(m_ym.begin(), m_ym.end(), x, m_mmw);
545 }
546 
547 doublereal Phase::moleFraction(size_t k) const
548 {
550  return m_ym[k] * m_mmw;
551 }
552 
553 doublereal Phase::moleFraction(const std::string& nameSpec) const
554 {
555  size_t iloc = speciesIndex(nameSpec);
556  if (iloc != npos) {
557  return moleFraction(iloc);
558  } else {
559  return 0.0;
560  }
561 }
562 
563 const doublereal* Phase::moleFractdivMMW() const
564 {
565  return &m_ym[0];
566 }
567 
568 doublereal Phase::massFraction(size_t k) const
569 {
571  return m_y[k];
572 }
573 
574 doublereal Phase::massFraction(const std::string& nameSpec) const
575 {
576  size_t iloc = speciesIndex(nameSpec);
577  if (iloc != npos) {
578  return massFractions()[iloc];
579  } else {
580  return 0.0;
581  }
582 }
583 
584 void Phase::getMassFractions(doublereal* const y) const
585 {
586  copy(m_y.begin(), m_y.end(), y);
587 }
588 
589 doublereal Phase::concentration(const size_t k) const
590 {
592  return m_y[k] * m_dens * m_rmolwts[k];
593 }
594 
595 void Phase::getConcentrations(doublereal* const c) const
596 {
597  scale(m_ym.begin(), m_ym.end(), c, m_dens);
598 }
599 
600 void Phase::setConcentrations(const doublereal* const conc)
601 {
602  // Use m_y as temporary storage for non-negative concentrations
603  doublereal sum = 0.0, norm = 0.0;
604  for (size_t k = 0; k != m_kk; ++k) {
605  double ck = std::max(conc[k], 0.0); // Ignore negative concentrations
606  m_y[k] = ck;
607  sum += ck * m_molwts[k];
608  norm += ck;
609  }
610  m_mmw = sum/norm;
611  setDensity(sum);
612  doublereal rsum = 1.0/sum;
613  for (size_t k = 0; k != m_kk; ++k) {
614  m_ym[k] = m_y[k] * rsum;
615  m_y[k] = m_ym[k] * m_molwts[k]; // m_y is now the mass fraction
616  }
618 }
619 
620 void Phase::setConcentrationsNoNorm(const double* const conc)
621 {
622  doublereal sum = 0.0, norm = 0.0;
623  for (size_t k = 0; k != m_kk; ++k) {
624  sum += conc[k] * m_molwts[k];
625  norm += conc[k];
626  }
627  m_mmw = sum/norm;
628  setDensity(sum);
629  doublereal rsum = 1.0/sum;
630  for (size_t k = 0; k != m_kk; ++k) {
631  m_ym[k] = conc[k] * rsum;
632  m_y[k] = m_ym[k] * m_molwts[k];
633  }
635 }
636 
637 doublereal Phase::elementalMassFraction(const size_t m) const
638 {
640  doublereal Z_m = 0.0;
641  for (size_t k = 0; k != m_kk; ++k) {
642  Z_m += nAtoms(k, m) * atomicWeight(m) / molecularWeight(k)
643  * massFraction(k);
644  }
645  return Z_m;
646 }
647 
648 doublereal Phase::elementalMoleFraction(const size_t m) const
649 {
651  double denom = 0;
652  for (size_t k = 0; k < m_kk; k++) {
653  double atoms = 0;
654  for (size_t j = 0; j < nElements(); j++) {
655  atoms += nAtoms(k, j);
656  }
657  denom += atoms * moleFraction(k);
658  }
659  doublereal numerator = 0.0;
660  for (size_t k = 0; k != m_kk; ++k) {
661  numerator += nAtoms(k, m) * moleFraction(k);
662  }
663  return numerator / denom;
664 }
665 
666 doublereal Phase::molarDensity() const
667 {
668  return density()/meanMolecularWeight();
669 }
670 
671 void Phase::setMolarDensity(const doublereal molar_density)
672 {
673  m_dens = molar_density*meanMolecularWeight();
674 }
675 
676 doublereal Phase::molarVolume() const
677 {
678  return 1.0/molarDensity();
679 }
680 
681 doublereal Phase::chargeDensity() const
682 {
683  doublereal cdens = 0.0;
684  for (size_t k = 0; k < m_kk; k++) {
685  cdens += charge(k)*moleFraction(k);
686  }
687  return cdens * Faraday;
688 }
689 
690 doublereal Phase::mean_X(const doublereal* const Q) const
691 {
692  return m_mmw*std::inner_product(m_ym.begin(), m_ym.end(), Q, 0.0);
693 }
694 
695 doublereal Phase::mean_X(const vector_fp& Q) const
696 {
697  return m_mmw*std::inner_product(m_ym.begin(), m_ym.end(), Q.begin(), 0.0);
698 }
699 
700 doublereal Phase::sum_xlogx() const
701 {
702  return m_mmw* Cantera::sum_xlogx(m_ym.begin(), m_ym.end()) + log(m_mmw);
703 }
704 
705 size_t Phase::addElement(const std::string& symbol, doublereal weight,
706  int atomic_number, doublereal entropy298,
707  int elem_type)
708 {
709  // Look up the atomic weight if not given
710  if (weight == 0.0) {
711  try {
712  weight = getElementWeight(symbol);
713  } catch (CanteraError&) {
714  // assume this is just a custom element with zero atomic weight
715  }
716  } else if (weight == -12345.0) {
717  weight = getElementWeight(symbol);
718  }
719 
720  // Check for duplicates
721  auto iter = find(m_elementNames.begin(), m_elementNames.end(), symbol);
722  if (iter != m_elementNames.end()) {
723  size_t m = iter - m_elementNames.begin();
724  if (m_atomicWeights[m] != weight) {
725  throw CanteraError("Phase::addElement",
726  "Duplicate elements ({}) have different weights", symbol);
727  } else {
728  // Ignore attempt to add duplicate element with the same weight
729  return m;
730  }
731  }
732 
733  // Add the new element
734  m_atomicWeights.push_back(weight);
735  m_elementNames.push_back(symbol);
736  m_atomicNumbers.push_back(atomic_number);
737  m_entropy298.push_back(entropy298);
738  if (symbol == "E") {
740  } else {
741  m_elem_type.push_back(elem_type);
742  }
743  m_mm++;
744 
745  // Update species compositions
746  if (m_kk) {
748  m_speciesComp.resize(m_kk*m_mm, 0.0);
749  for (size_t k = 0; k < m_kk; k++) {
750  size_t m_old = m_mm - 1;
751  for (size_t m = 0; m < m_old; m++) {
752  m_speciesComp[k * m_mm + m] = old[k * (m_old) + m];
753  }
754  m_speciesComp[k * (m_mm) + (m_mm-1)] = 0.0;
755  }
756  }
757 
758  return m_mm-1;
759 }
760 
761 bool Phase::addSpecies(shared_ptr<Species> spec) {
762  if (m_species.find(ba::to_lower_copy(spec->name)) != m_species.end()) {
763  throw CanteraError("Phase::addSpecies",
764  "Phase '{}' already contains a species named '{}'.",
765  m_name, spec->name);
766  }
767  vector_fp comp(nElements());
768  for (const auto& elem : spec->composition) {
769  size_t m = elementIndex(elem.first);
770  if (m == npos) { // Element doesn't exist in this phase
771  switch (m_undefinedElementBehavior) {
772  case UndefElement::ignore:
773  return false;
774 
775  case UndefElement::add:
776  addElement(elem.first);
777  comp.resize(nElements());
778  m = elementIndex(elem.first);
779  break;
780 
781  case UndefElement::error:
782  default:
783  throw CanteraError("Phase::addSpecies",
784  "Species '{}' contains an undefined element '{}'.",
785  spec->name, elem.first);
786  }
787  }
788  comp[m] = elem.second;
789  }
790 
791  m_speciesNames.push_back(spec->name);
792  m_species[ba::to_lower_copy(spec->name)] = spec;
793  m_speciesIndices[ba::to_lower_copy(spec->name)] = m_kk;
794  m_speciesCharge.push_back(spec->charge);
795  m_speciesSize.push_back(spec->size);
796  size_t ne = nElements();
797 
798  double wt = 0.0;
799  const vector_fp& aw = atomicWeights();
800  if (spec->charge != 0.0) {
801  size_t eindex = elementIndex("E");
802  if (eindex != npos) {
803  doublereal ecomp = comp[eindex];
804  if (fabs(spec->charge + ecomp) > 0.001) {
805  if (ecomp != 0.0) {
806  throw CanteraError("Phase::addSpecies",
807  "Input charge and element E compositions differ "
808  "for species " + spec->name);
809  } else {
810  // Just fix up the element E composition based on the input
811  // species charge
812  comp[eindex] = -spec->charge;
813  }
814  }
815  } else {
816  addElement("E", 0.000545, 0, 0.0, CT_ELEM_TYPE_ELECTRONCHARGE);
817  ne = nElements();
818  eindex = elementIndex("E");
819  comp.resize(ne);
820  comp[ne - 1] = - spec->charge;
821  }
822  }
823  for (size_t m = 0; m < ne; m++) {
824  m_speciesComp.push_back(comp[m]);
825  wt += comp[m] * aw[m];
826  }
827 
828  // Some surface phases may define species representing empty sites
829  // that have zero molecular weight. Give them a very small molecular
830  // weight to avoid dividing by zero.
831  wt = std::max(wt, Tiny);
832  m_molwts.push_back(wt);
833  m_rmolwts.push_back(1.0/wt);
834  m_kk++;
835 
836  // Ensure that the Phase has a valid mass fraction vector that sums to
837  // one. We will assume that species 0 has a mass fraction of 1.0 and mass
838  // fraction of all other species is 0.0.
839  if (m_kk == 1) {
840  m_y.push_back(1.0);
841  m_ym.push_back(m_rmolwts[0]);
842  m_mmw = 1.0 / m_ym[0];
843  } else {
844  m_y.push_back(0.0);
845  m_ym.push_back(0.0);
846  }
847  invalidateCache();
848  return true;
849 }
850 
851 void Phase::modifySpecies(size_t k, shared_ptr<Species> spec)
852 {
853  if (speciesName(k) != spec->name) {
854  throw CanteraError("Phase::modifySpecies",
855  "New species name '{}' does not match existing name '{}'",
856  spec->name, speciesName(k));
857  }
858  const shared_ptr<Species>& old = m_species[ba::to_lower_copy(spec->name)];
859  if (spec->composition != old->composition) {
860  throw CanteraError("Phase::modifySpecies",
861  "New composition for '{}' does not match existing composition",
862  spec->name);
863  }
864  m_species[ba::to_lower_copy(spec->name)] = spec;
865  invalidateCache();
866 }
867 
868 shared_ptr<Species> Phase::species(const std::string& name) const
869 {
870  return m_species.at(ba::to_lower_copy(name));
871 }
872 
873 shared_ptr<Species> Phase::species(size_t k) const
874 {
875  return species(m_speciesNames[k]);
876 }
877 
879  m_undefinedElementBehavior = UndefElement::ignore;
880 }
881 
883  m_undefinedElementBehavior = UndefElement::add;
884 }
885 
887  m_undefinedElementBehavior = UndefElement::error;
888 }
889 
890 bool Phase::ready() const
891 {
892  return (m_kk > 0);
893 }
894 
896  m_cache.clear();
897 }
898 
900  m_stateNum++;
901 }
902 
903 } // namespace Cantera
Phase()
Default constructor.
Definition: Phase.cpp:20
std::map< std::string, doublereal > compositionMap
Map connecting a string name with a double.
Definition: ct_defs.h:149
const vector_fp & molecularWeights() const
Return a const reference to the internal vector of molecular weights.
Definition: Phase.cpp:513
virtual void setMoleFractions_NoNorm(const doublereal *const x)
Set the mole fractions to the specified values without normalizing.
Definition: Phase.cpp:359
vector_fp m_y
Mass fractions of the species.
Definition: Phase.h:837
void setState_RY(doublereal rho, doublereal *y)
Set the density (kg/m^3) and mass fractions.
Definition: Phase.cpp:490
doublereal molarVolume() const
Molar volume (m^3/kmol).
Definition: Phase.cpp:676
Array size error.
Definition: ctexceptions.h:134
std::vector< std::string > m_elementNames
element names
Definition: Phase.h:856
size_t nElements() const
Number of elements.
Definition: Phase.cpp:161
void restoreState(const vector_fp &state)
Restore a state saved on a previous call to saveState.
Definition: Phase.cpp:309
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:452
XML_Node * findXMLPhase(XML_Node *root, const std::string &idtarget)
Search an XML_Node tree for a named phase XML_Node.
Definition: xml.cpp:1038
void getMassFractions(doublereal *const y) const
Get the species mass fractions.
Definition: Phase.cpp:584
vector_fp m_atomicWeights
element atomic weights (kg kmol-1)
Definition: Phase.h:854
doublereal temperature() const
Temperature (K).
Definition: Phase.h:601
const doublereal * massFractions() const
Return a const pointer to the mass fraction array.
Definition: Phase.h:478
Various templated functions that carry out common vector operations (see Templated Utility Functions)...
size_t speciesIndex(const std::string &name) const
Returns the index of a species named &#39;name&#39; within the Phase object.
Definition: Phase.cpp:251
void saveState(vector_fp &state) const
Save the current internal state of the phase.
Definition: Phase.cpp:297
doublereal moleFraction(size_t k) const
Return the mole fraction of a single species.
Definition: Phase.cpp:547
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:800
Header file for class Phase.
size_t elementIndex(const std::string &name) const
Return the index of element named &#39;name&#39;.
Definition: Phase.cpp:186
doublereal sum_xlogx() const
Evaluate .
Definition: Phase.cpp:700
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:860
compositionMap getMoleFractionsByName(double threshold=0.0) const
Get the mole fractions by name.
Definition: Phase.cpp:518
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:97
std::map< std::string, size_t > m_speciesIndices
Map of species names to indices.
Definition: Phase.h:851
void checkSpeciesIndex(size_t k) const
Check that the specified species index is in range.
Definition: Phase.cpp:278
vector_fp m_speciesSize
Vector of species sizes.
Definition: Phase.h:798
size_t nSpecies() const
Returns the number of species in the phase.
Definition: Phase.h:262
STL namespace.
virtual doublereal density() const
Density (kg/m^3).
Definition: Phase.h:607
doublereal m_mmw
mean molecular weight of the mixture (kg kmol-1)
Definition: Phase.h:826
Class Phase is the base class for phases of matter, managing the species and elements in a phase...
Definition: Phase.h:96
#define CT_ELEM_TYPE_ELECTRONCHARGE
This refers to conservation of electrons.
Definition: Elements.h:43
virtual bool ready() const
Returns a bool indicating whether the object is ready for use.
Definition: Phase.cpp:890
Unary operator to multiply the argument by a constant.
Definition: utilities.h:33
UndefElement::behavior m_undefinedElementBehavior
Flag determining behavior when adding species with an undefined element.
Definition: Phase.h:805
std::string m_name
Name of the phase.
Definition: Phase.h:817
const std::vector< std::string > & speciesNames() const
Return a const reference to the vector of species names.
Definition: Phase.cpp:273
doublereal mean_X(const doublereal *const Q) const
Evaluate the mole-fraction-weighted mean of an array Q.
Definition: Phase.cpp:690
int atomicNumber(size_t m) const
Atomic number of element m.
Definition: Phase.cpp:220
void setName(const std::string &nm)
Sets the string name for the phase.
Definition: Phase.cpp:156
doublereal elementalMoleFraction(const size_t m) const
Elemental mole fraction of element m.
Definition: Phase.cpp:648
void throwUndefinedElements()
Set the behavior when adding a species containing undefined elements to throw an exception.
Definition: Phase.cpp:886
int m_stateNum
State Change variable.
Definition: Phase.h:845
size_t m_ndim
Dimensionality of the phase.
Definition: Phase.h:788
doublereal atomicWeight(size_t m) const
Atomic weight of element m.
Definition: Phase.cpp:201
void ignoreUndefinedElements()
Set behavior when adding a species containing undefined elements to just skip the species...
Definition: Phase.cpp:878
std::vector< std::string > m_speciesNames
Vector of the species names.
Definition: Phase.h:848
void setState_TRX(doublereal t, doublereal dens, const doublereal *x)
Set the internally stored temperature (K), density, and mole fractions.
Definition: Phase.cpp:431
void getAtoms(size_t k, double *atomArray) const
Get a vector containing the atomic composition of species k.
Definition: Phase.cpp:244
void checkElementArraySize(size_t mm) const
Check that an array size is at least nElements().
Definition: Phase.cpp:173
doublereal molarDensity() const
Molar density (kmol/m^3).
Definition: Phase.cpp:666
shared_ptr< Species > species(const std::string &name) const
Return the Species object for the named species.
Definition: Phase.cpp:868
std::string speciesName(size_t k) const
Name of the species with index k.
Definition: Phase.cpp:267
virtual void compositionChanged()
Apply changes to the state which are needed after the composition changes.
Definition: Phase.cpp:899
doublereal entropyElement298(size_t m) const
Entropy of the element in its standard state at 298 K and 1 bar.
Definition: Phase.cpp:206
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:292
void clear()
Clear all cached values.
Definition: ValueCache.cpp:27
const doublereal * moleFractdivMMW() const
Returns a const pointer to the start of the moleFraction/MW array.
Definition: Phase.cpp:563
void setMoleFractionsByName(const compositionMap &xMap)
Set the species mole fractions by name.
Definition: Phase.cpp:368
ValueCache m_cache
Cached for saved calculations within each ThermoPhase.
Definition: Phase.h:761
void setMassFractionsByName(const compositionMap &yMap)
Set the species mass fractions by name.
Definition: Phase.cpp:412
virtual void modifySpecies(size_t k, shared_ptr< Species > spec)
Modify the thermodynamic data associated with a species.
Definition: Phase.cpp:851
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:65
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:438
double getElementWeight(const std::string &ename)
Get the atomic weight of an element.
Definition: Elements.cpp:172
virtual void invalidateCache()
Invalidate any cached values which are normally updated only when a change in state is detected...
Definition: Phase.cpp:895
virtual void setConcentrations(const doublereal *const conc)
Set the concentrations to the specified values within the phase.
Definition: Phase.cpp:600
const U & getValue(const std::map< T, U > &m, const T &key)
Const accessor for a value in a std::map.
Definition: utilities.h:537
virtual void setMoleFractions(const doublereal *const x)
Set the mole fractions to the specified values.
Definition: Phase.cpp:327
std::string parseSpeciesName(const std::string &nameStr, std::string &phaseName)
Parse a name string, separating out the phase name from the species name.
doublereal sum_xlogx(InputIter begin, InputIter end)
Compute .
Definition: utilities.h:389
doublereal concentration(const size_t k) const
Concentration of species k.
Definition: Phase.cpp:589
virtual bool addSpecies(shared_ptr< Species > spec)
Add a Species to this Phase.
Definition: Phase.cpp:761
void getMoleFractions(doublereal *const x) const
Get the species mole fraction vector.
Definition: Phase.cpp:542
virtual void setMolarDensity(const doublereal molarDensity)
Set the internally stored molar density (kmol/m^3) of the phase.
Definition: Phase.cpp:671
XML_Node & xml() const
Returns a const reference to the XML_Node that describes the phase.
Definition: Phase.cpp:117
virtual void setConcentrationsNoNorm(const double *const conc)
Set the concentrations without ignoring negative concentrations.
Definition: Phase.cpp:620
doublereal dot(InputIter x_begin, InputIter x_end, InputIter2 y_begin)
Function that calculates a templated inner product.
Definition: utilities.h:107
compositionMap getMassFractionsByName(double threshold=0.0) const
Get the mass fractions by name.
Definition: Phase.cpp:530
void copy(XML_Node *const node_dest) const
Copy all of the information in the current XML_Node tree into the destination XML_Node tree...
Definition: xml.cpp:825
#define ENTROPY298_UNKNOWN
Number indicating we don&#39;t know the entropy of the element in its most stable state at 298...
Definition: Elements.h:87
virtual void setMassFractions_NoNorm(const doublereal *const y)
Set the mass fractions to the specified values without normalizing.
Definition: Phase.cpp:401
void setState_TX(doublereal t, doublereal *x)
Set the internally stored temperature (K) and mole fractions.
Definition: Phase.cpp:472
XML_Node & root() const
Return the root of the current XML_Node tree.
Definition: xml.cpp:1025
vector_int m_elem_type
Vector of element types.
Definition: Phase.h:857
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.
doublereal elementalMassFraction(const size_t m) const
Elemental mass fraction of element m.
Definition: Phase.cpp:637
#define AssertTrace(expr)
Assertion must be true or an error is thrown.
Definition: ctexceptions.h:239
#define AssertThrowMsg(expr, procedure,...)
Assertion must be true or an error is thrown.
Definition: ctexceptions.h:270
doublereal chargeDensity() const
Charge density [C/m^3].
Definition: Phase.cpp:681
std::string id() const
Return the string id for the phase.
Definition: Phase.cpp:141
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:705
void checkSpeciesArraySize(size_t kk) const
Check that an array size is at least nSpecies().
Definition: Phase.cpp:285
vector_fp m_molwts
species molecular weights (kg kmol-1)
Definition: Phase.h:839
void setState_TY(doublereal t, doublereal *y)
Set the internally stored temperature (K) and mass fractions.
Definition: Phase.cpp:478
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
doublereal meanMolecularWeight() const
The mean molecular weight. Units: (kg/kmol)
Definition: Phase.h:661
void addUndefinedElements()
Set behavior when adding a species containing undefined elements to add those elements to the phase...
Definition: Phase.cpp:882
size_t m_mm
Number of elements.
Definition: Phase.h:853
virtual void setTemperature(const doublereal temp)
Set the internally stored temperature of the phase (K).
Definition: Phase.h:637
void scale(InputIter begin, InputIter end, OutputIter out, S scale_factor)
Multiply elements of an array by a scale factor.
Definition: utilities.h:130
const doublereal Tiny
Small number to compare differences of mole fractions against.
Definition: ct_defs.h:143
std::string m_id
ID of the phase.
Definition: Phase.h:812
doublereal m_dens
Density (kg m-3).
Definition: Phase.h:824
vector_fp m_ym
m_ym[k] = mole fraction of species k divided by the mean molecular weight of mixture.
Definition: Phase.h:830
int elementType(size_t m) const
Return the element constraint type Possible types include:
Definition: Phase.cpp:225
std::string id() const
Return the id attribute, if present.
Definition: xml.cpp:428
void getMolecularWeights(vector_fp &weights) const
Copy the vector of molecular weights into vector weights.
Definition: Phase.cpp:502
XML_Node * m_xml
XML node containing the XML info for this phase.
Definition: Phase.h:808
std::string name() const
Return the name of the phase.
Definition: Phase.cpp:151
vector_int m_atomicNumbers
element atomic numbers
Definition: Phase.h:855
Contains declarations for string manipulation functions within Cantera.
doublereal m_temp
Temperature (K). This is an independent variable.
Definition: Phase.h:819
virtual void setMassFractions(const doublereal *const y)
Set the mass fractions to the specified values and normalize them.
Definition: Phase.cpp:387
vector_fp m_rmolwts
inverse of species molecular weights (kmol kg-1)
Definition: Phase.h:841
vector_fp m_speciesComp
Atomic composition of the species.
Definition: Phase.h:793
void setXMLdata(XML_Node &xmlPhase)
Stores the XML tree information for the current phase.
Definition: Phase.cpp:122
void setState_RX(doublereal rho, doublereal *x)
Set the density (kg/m^3) and mole fractions.
Definition: Phase.cpp:484
size_t m_kk
Number of species in the phase.
Definition: Phase.h:784
An array index is out of range.
Definition: ctexceptions.h:164
int changeElementType(int m, int elem_type)
Change the element type of the mth constraint Reassigns an element type.
Definition: Phase.cpp:230
void setID(const std::string &id)
Set the string id for the phase.
Definition: Phase.cpp:146
doublereal molecularWeight(size_t k) const
Molecular weight of species k.
Definition: Phase.cpp:496
Namespace for the Cantera kernel.
Definition: application.cpp:29
void getConcentrations(doublereal *const c) const
Get the species concentrations (kmol/m^3).
Definition: Phase.cpp:595
doublereal nAtoms(size_t k, size_t m) const
Number of atoms of element m in species k.
Definition: Phase.cpp:237
void setState_TR(doublereal t, doublereal rho)
Set the internally stored temperature (K) and density (kg/m^3)
Definition: Phase.cpp:466
const std::vector< std::string > & elementNames() const
Return a read-only reference to the vector of element names.
Definition: Phase.cpp:196
const vector_fp & atomicWeights() const
Return a read-only reference to the vector of atomic weights.
Definition: Phase.cpp:215
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:577
std::string elementName(size_t m) const
Name of the element with index m.
Definition: Phase.cpp:180
void checkElementIndex(size_t m) const
Check that the specified element index is in range.
Definition: Phase.cpp:166
virtual void setDensity(const doublereal density_)
Set the internally stored density (kg/m^3) of the phase.
Definition: Phase.h:622
doublereal massFraction(size_t k) const
Return the mass fraction of a single species.
Definition: Phase.cpp:568