Cantera  2.1.2
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"
12 
13 using namespace std;
14 
15 namespace Cantera
16 {
17 
18 Phase::Phase() :
19  m_kk(0),
20  m_ndim(3),
21  m_xml(new XML_Node("phase")),
22  m_id("<phase>"),
23  m_name(""),
24  m_temp(0.001),
25  m_dens(0.001),
26  m_mmw(0.0),
27  m_stateNum(-1),
28  m_speciesFrozen(false),
29  m_elementsFrozen(false),
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_xml(0),
39  m_id("<phase>"),
40  m_name(""),
41  m_temp(0.001),
42  m_dens(0.001),
43  m_mmw(0.0),
44  m_stateNum(-1),
45  m_speciesFrozen(false) ,
46  m_elementsFrozen(false),
47  m_mm(0),
48  m_elem_type(0)
49 {
50  // Use the assignment operator to do the actual copying
51  *this = operator=(right);
52 }
53 
55 {
56  // Check for self assignment.
57  if (this == &right) {
58  return *this;
59  }
60 
61  // Handle our own data
62  m_kk = right.m_kk;
63  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 
78 
79  m_mm = right.m_mm;
84  m_entropy298 = right.m_entropy298;
85  m_elem_type = right.m_elem_type;
86  /*
87  * This is a little complicated. -> Because we delete m_xml
88  * in the destructor, we own m_xml completely, and we need
89  * to have our own individual copies of the XML data tree
90  * in each object
91  */
92  if (m_xml) {
93  delete m_xml;
94  m_xml = 0;
95  }
96  if (right.m_xml) {
97  m_xml = new XML_Node();
98  (right.m_xml)->copy(m_xml);
99  }
100  m_id = right.m_id;
101  m_name = right.m_name;
102 
103  return *this;
104 }
105 
107 {
108  if (m_xml) {
109  delete m_xml;
110  m_xml = 0;
111  }
112 }
113 
115 {
116  return *m_xml;
117 }
118 
119 std::string Phase::id() const
120 {
121  return m_id;
122 }
123 
124 void Phase::setID(const std::string& id_)
125 {
126  m_id = id_;
127 }
128 
129 std::string Phase::name() const
130 {
131  return m_name;
132 }
133 
134 void Phase::setName(const std::string& nm)
135 {
136  m_name = nm;
137 }
138 
139 size_t Phase::nElements() const
140 {
141  return m_mm;
142 }
143 
144 void Phase::checkElementIndex(size_t m) const
145 {
146  if (m >= m_mm) {
147  throw IndexError("checkElementIndex", "elements", m, m_mm-1);
148  }
149 }
150 
151 void Phase::checkElementArraySize(size_t mm) const
152 {
153  if (m_mm > mm) {
154  throw ArraySizeError("checkElementArraySize", mm, m_mm);
155  }
156 }
157 
158 string Phase::elementName(size_t m) const
159 {
161  return m_elementNames[m];
162 }
163 
164 size_t Phase::elementIndex(const std::string& elementName) const
165 {
166  for (size_t i = 0; i < m_mm; i++) {
167  if (m_elementNames[i] == elementName) {
168  return i;
169  }
170  }
171  return npos;
172 }
173 
174 const vector<string>& Phase::elementNames() const
175 {
176  return m_elementNames;
177 }
178 
179 doublereal Phase::atomicWeight(size_t m) const
180 {
181  return m_atomicWeights[m];
182 }
183 
184 doublereal Phase::entropyElement298(size_t m) const
185 {
187  "Elements::entropy298",
188  "Entropy at 298 K of element is unknown");
189  AssertTrace(m < m_mm);
190  return m_entropy298[m];
191 }
192 
194 {
195  return m_atomicWeights;
196 }
197 
198 int Phase::atomicNumber(size_t m) const
199 {
200  return m_atomicNumbers[m];
201 }
202 
203 int Phase::elementType(size_t m) const
204 {
205  return m_elem_type[m];
206 }
207 
208 int Phase::changeElementType(int m, int elem_type)
209 {
210  int old = m_elem_type[m];
211  m_elem_type[m] = elem_type;
212  return old;
213 }
214 
215 doublereal Phase::nAtoms(size_t k, size_t m) const
216 {
219  return m_speciesComp[m_mm * k + m];
220 }
221 
222 void Phase::getAtoms(size_t k, double* atomArray) const
223 {
224  for (size_t m = 0; m < m_mm; m++) {
225  atomArray[m] = (double) m_speciesComp[m_mm * k + m];
226  }
227 }
228 
229 size_t Phase::speciesIndex(const std::string& nameStr) const
230 {
231  std::string pn;
232  std::string sn = parseSpeciesName(nameStr, pn);
233  if (pn == "" || pn == m_name || pn == m_id) {
234  vector<string>::const_iterator it = m_speciesNames.begin();
235  for (size_t k = 0; k < m_kk; k++) {
236  if (*it == sn) {
237  return k;
238  }
239  ++it;
240  }
241  return npos;
242  }
243  return npos;
244 }
245 
246 string Phase::speciesName(size_t k) const
247 {
249  return m_speciesNames[k];
250 }
251 
252 const vector<string>& Phase::speciesNames() const
253 {
254  return m_speciesNames;
255 }
256 
257 void Phase::checkSpeciesIndex(size_t k) const
258 {
259  if (k >= m_kk) {
260  throw IndexError("checkSpeciesIndex", "species", k, m_kk-1);
261  }
262 }
263 
264 void Phase::checkSpeciesArraySize(size_t kk) const
265 {
266  if (m_kk > kk) {
267  throw ArraySizeError("checkSpeciesArraySize", kk, m_kk);
268  }
269 }
270 
271 std::string Phase::speciesSPName(int k) const
272 {
273  std::string sn = speciesName(k);
274  return m_name + ":" + sn;
275 }
276 
277 void Phase::saveState(vector_fp& state) const
278 {
279  state.resize(nSpecies() + 2);
280  saveState(state.size(),&(state[0]));
281 }
282 void Phase::saveState(size_t lenstate, doublereal* state) const
283 {
284  state[0] = temperature();
285  state[1] = density();
286  getMassFractions(state + 2);
287 }
288 
289 void Phase::restoreState(const vector_fp& state)
290 {
291  restoreState(state.size(),&state[0]);
292 }
293 
294 void Phase::restoreState(size_t lenstate, const doublereal* state)
295 {
296  if (lenstate >= nSpecies() + 2) {
297  setMassFractions_NoNorm(state + 2);
298  setTemperature(state[0]);
299  setDensity(state[1]);
300  } else {
301  throw ArraySizeError("Phase::restoreState",
302  lenstate,nSpecies()+2);
303  }
304 }
305 
306 void Phase::setMoleFractions(const doublereal* const x)
307 {
308  // Use m_y as a temporary work vector for the non-negative mole fractions
309  doublereal norm = 0.0;
310  /*
311  * sum is calculated below as the unnormalized molecular weight
312  */
313  doublereal sum = 0;
314  for (size_t k = 0; k < m_kk; k++) {
315  double xk = std::max(x[k], 0.0); // Ignore negative mole fractions
316  m_y[k] = xk;
317  norm += xk;
318  sum += m_molwts[k] * xk;
319  }
320  /*
321  * Set m_ym_ to the normalized mole fractions divided by the normalized mean molecular weight:
322  * m_ym_k = X_k / (sum_k X_k M_k)
323  */
324  // transform(m_y.begin(), m_y.end(), m_ym.begin(), timesConstant<double>(1.0/sum));
325  const doublereal invSum = 1.0/sum;
326  for (size_t k=0; k < m_kk; k++) {
327  m_ym[k] = m_y[k]*invSum;
328  }
329  /*
330  * Now set m_y to the normalized mass fractions
331  * m_y = X_k M_k / (sum_k X_k M_k)
332  */
333  // transform(m_ym.begin(), m_ym.begin() + m_kk, m_molwts.begin(), m_y.begin(), multiplies<double>());
334  for (size_t k=0; k < m_kk; k++) {
335  m_y[k] = m_ym[k] * m_molwts[k];
336  }
337  /*
338  * Calculate the normalized molecular weight
339  */
340  m_mmw = sum/norm;
341  m_stateNum++;
342 }
343 
344 void Phase::setMoleFractions_NoNorm(const doublereal* const x)
345 {
346  m_mmw = dot(x, x + m_kk, m_molwts.begin());
347  doublereal rmmw = 1.0/m_mmw;
348  transform(x, x + m_kk, m_ym.begin(), timesConstant<double>(rmmw));
349  transform(m_ym.begin(), m_ym.begin() + m_kk, m_molwts.begin(),
350  m_y.begin(), multiplies<double>());
351  m_stateNum++;
352 }
353 
355 {
356  size_t kk = nSpecies();
357  doublereal x;
358  vector_fp mf(kk, 0.0);
359  for (size_t k = 0; k < kk; k++) {
360  x = xMap[speciesName(k)];
361  if (x > 0.0) {
362  mf[k] = x;
363  }
364  }
365  setMoleFractions(&mf[0]);
366 }
367 
368 void Phase::setMoleFractionsByName(const std::string& x)
369 {
372 }
373 
374 void Phase::setMassFractions(const doublereal* const y)
375 {
376  for (size_t k = 0; k < m_kk; k++) {
377  m_y[k] = std::max(y[k], 0.0); // Ignore negative mass fractions
378  }
379  doublereal norm = accumulate(m_y.begin(), m_y.end(), 0.0);
380  scale(m_y.begin(), m_y.end(), m_y.begin(), 1.0/norm);
381 
382  transform(m_y.begin(), m_y.end(), m_rmolwts.begin(),
383  m_ym.begin(), multiplies<double>());
384  m_mmw = 1.0 / accumulate(m_ym.begin(), m_ym.end(), 0.0);
385  m_stateNum++;
386 }
387 
388 void Phase::setMassFractions_NoNorm(const doublereal* const y)
389 {
390  doublereal sum = 0.0;
391  copy(y, y + m_kk, m_y.begin());
392  transform(m_y.begin(), m_y.end(), m_rmolwts.begin(), m_ym.begin(),
393  multiplies<double>());
394  sum = accumulate(m_ym.begin(), m_ym.end(), 0.0);
395  m_mmw = 1.0/sum;
396  m_stateNum++;
397 }
398 
400 {
401  size_t kk = nSpecies();
402  doublereal y;
403  vector_fp mf(kk, 0.0);
404  for (size_t k = 0; k < kk; k++) {
405  y = yMap[speciesName(k)];
406  if (y > 0.0) {
407  mf[k] = y;
408  }
409  }
410  setMassFractions(&mf[0]);
411 }
412 
413 void Phase::setMassFractionsByName(const std::string& y)
414 {
417 }
418 
419 void Phase::setState_TRX(doublereal t, doublereal dens, const doublereal* x)
420 {
421  setMoleFractions(x);
422  setTemperature(t);
423  setDensity(dens);
424 }
425 
426 void Phase::setState_TNX(doublereal t, doublereal n, const doublereal* x)
427 {
428  setMoleFractions(x);
429  setTemperature(t);
430  setMolarDensity(n);
431 }
432 
433 void Phase::setState_TRX(doublereal t, doublereal dens, compositionMap& x)
434 {
436  setTemperature(t);
437  setDensity(dens);
438 }
439 
440 void Phase::setState_TRY(doublereal t, doublereal dens, const doublereal* y)
441 {
442  setMassFractions(y);
443  setTemperature(t);
444  setDensity(dens);
445 }
446 
447 void Phase::setState_TRY(doublereal t, doublereal dens, compositionMap& y)
448 {
450  setTemperature(t);
451  setDensity(dens);
452 }
453 
454 void Phase::setState_TR(doublereal t, doublereal rho)
455 {
456  setTemperature(t);
457  setDensity(rho);
458 }
459 
460 void Phase::setState_TX(doublereal t, doublereal* x)
461 {
462  setTemperature(t);
463  setMoleFractions(x);
464 }
465 
466 void Phase::setState_TY(doublereal t, doublereal* y)
467 {
468  setTemperature(t);
469  setMassFractions(y);
470 }
471 
472 void Phase::setState_RX(doublereal rho, doublereal* x)
473 {
474  setMoleFractions(x);
475  setDensity(rho);
476 }
477 
478 void Phase::setState_RY(doublereal rho, doublereal* y)
479 {
480  setMassFractions(y);
481  setDensity(rho);
482 }
483 
484 doublereal Phase::molecularWeight(size_t k) const
485 {
487  return m_molwts[k];
488 }
489 
491 {
492  const vector_fp& mw = molecularWeights();
493  if (weights.size() < mw.size()) {
494  weights.resize(mw.size());
495  }
496  copy(mw.begin(), mw.end(), weights.begin());
497 }
498 
499 void Phase::getMolecularWeights(doublereal* weights) const
500 {
501  const vector_fp& mw = molecularWeights();
502  copy(mw.begin(), mw.end(), weights);
503 }
504 
506 {
507  return m_molwts;
508 }
509 
511 {
512  x.clear();
513  size_t kk = nSpecies();
514  for (size_t k = 0; k < kk; k++) {
515  x[speciesName(k)] = Phase::moleFraction(k);
516  }
517 }
518 
519 void Phase::getMoleFractions(doublereal* const x) const
520 {
521  scale(m_ym.begin(), m_ym.end(), x, m_mmw);
522 }
523 
524 doublereal Phase::moleFraction(size_t k) const
525 {
527  return m_ym[k] * m_mmw;
528 }
529 
530 doublereal Phase::moleFraction(const std::string& nameSpec) const
531 {
532  size_t iloc = speciesIndex(nameSpec);
533  if (iloc != npos) {
534  return moleFraction(iloc);
535  } else {
536  return 0.0;
537  }
538 }
539 
540 const doublereal* Phase::moleFractdivMMW() const
541 {
542  return &m_ym[0];
543 }
544 
545 doublereal Phase::massFraction(size_t k) const
546 {
548  return m_y[k];
549 }
550 
551 doublereal Phase::massFraction(const std::string& nameSpec) const
552 {
553  size_t iloc = speciesIndex(nameSpec);
554  if (iloc != npos) {
555  return massFractions()[iloc];
556  } else {
557  return 0.0;
558  }
559 }
560 
561 void Phase::getMassFractions(doublereal* const y) const
562 {
563  copy(m_y.begin(), m_y.end(), y);
564 }
565 
566 doublereal Phase::concentration(const size_t k) const
567 {
569  return m_y[k] * m_dens * m_rmolwts[k] ;
570 }
571 
572 void Phase::getConcentrations(doublereal* const c) const
573 {
574  scale(m_ym.begin(), m_ym.end(), c, m_dens);
575 }
576 
577 void Phase::setConcentrations(const doublereal* const conc)
578 {
579  // Use m_y as temporary storage for non-negative concentrations
580  doublereal sum = 0.0, norm = 0.0;
581  for (size_t k = 0; k != m_kk; ++k) {
582  double ck = std::max(conc[k], 0.0); // Ignore negative concentrations
583  m_y[k] = ck;
584  sum += ck * m_molwts[k];
585  norm += ck;
586  }
587  m_mmw = sum/norm;
588  setDensity(sum);
589  doublereal rsum = 1.0/sum;
590  for (size_t k = 0; k != m_kk; ++k) {
591  m_ym[k] = m_y[k] * rsum;
592  m_y[k] = m_ym[k] * m_molwts[k]; // m_y is now the mass fraction
593  }
594  m_stateNum++;
595 }
596 
597 doublereal Phase::molarDensity() const
598 {
599  return density()/meanMolecularWeight();
600 }
601 
602 void Phase::setMolarDensity(const doublereal molar_density)
603 {
604  m_dens = molar_density*meanMolecularWeight();
605 }
606 
607 doublereal Phase::molarVolume() const
608 {
609  return 1.0/molarDensity();
610 }
611 
612 doublereal Phase::chargeDensity() const
613 {
614  size_t kk = nSpecies();
615  doublereal cdens = 0.0;
616  for (size_t k = 0; k < kk; k++) {
617  cdens += charge(k)*moleFraction(k);
618  }
619  cdens *= Faraday;
620  return cdens;
621 }
622 
623 doublereal Phase::mean_X(const doublereal* const Q) const
624 {
625  return m_mmw*std::inner_product(m_ym.begin(), m_ym.end(), Q, 0.0);
626 }
627 
628 doublereal Phase::mean_Y(const doublereal* const Q) const
629 {
630  return dot(m_y.begin(), m_y.end(), Q);
631 }
632 
633 doublereal Phase::sum_xlogx() const
634 {
635  return m_mmw* Cantera::sum_xlogx(m_ym.begin(), m_ym.end()) + log(m_mmw);
636 }
637 
638 doublereal Phase::sum_xlogQ(doublereal* Q) const
639 {
640  return m_mmw * Cantera::sum_xlogQ(m_ym.begin(), m_ym.end(), Q);
641 }
642 
643 void Phase::addElement(const std::string& symbol, doublereal weight)
644 {
645  if (weight == -12345.0) {
646  weight = LookupWtElements(symbol);
647  if (weight < 0.0) {
648  throw ElementsFrozen("addElement");
649  }
650  }
651  if (m_elementsFrozen) {
652  throw ElementsFrozen("addElement");
653  return;
654  }
655  m_atomicWeights.push_back(weight);
656  m_elementNames.push_back(symbol);
657  if (symbol == "E") {
659  } else {
660  m_elem_type.push_back(CT_ELEM_TYPE_ABSPOS);
661  }
662 
663  m_mm++;
664 }
665 
667 {
668  doublereal weight = fpValue(e["atomicWt"]);
669  string symbol = e["name"];
670  addElement(symbol, weight);
671 }
672 
673 void Phase::addUniqueElement(const std::string& symbol, doublereal weight,
674  int atomic_number, doublereal entropy298,
675  int elem_type)
676 {
677  if (weight == -12345.0) {
678  weight = LookupWtElements(symbol);
679  if (weight < 0.0) {
680  throw ElementsFrozen("addElement");
681  }
682  }
683  /*
684  * First decide if this element has been previously added
685  * by conducting a string search. If it unique, add it to
686  * the list.
687  */
688  int ifound = 0;
689  int i = 0;
690  for (vector<string>::const_iterator it = m_elementNames.begin();
691  it < m_elementNames.end(); ++it, ++i) {
692  if (*it == symbol) {
693  ifound = 1;
694  break;
695  }
696  }
697  if (!ifound) {
698  if (m_elementsFrozen) {
699  throw ElementsFrozen("addElement");
700  return;
701  }
702  m_atomicWeights.push_back(weight);
703  m_elementNames.push_back(symbol);
704  m_atomicNumbers.push_back(atomic_number);
705  m_entropy298.push_back(entropy298);
706  if (symbol == "E") {
708  } else {
709  m_elem_type.push_back(elem_type);
710  }
711  m_mm++;
712  } else {
713  if (m_atomicWeights[i] != weight) {
714  throw CanteraError("AddUniqueElement",
715  "Duplicate Elements (" + symbol + ") have different weights");
716  }
717  }
718 }
719 
721 {
722  doublereal weight = 0.0;
723  if (e.hasAttrib("atomicWt")) {
724  weight = fpValue(stripws(e["atomicWt"]));
725  }
726  int anum = 0;
727  if (e.hasAttrib("atomicNumber")) {
728  anum = atoi(stripws(e["atomicNumber"]).c_str());
729  }
730  string symbol = e["name"];
731  doublereal entropy298 = ENTROPY298_UNKNOWN;
732  if (e.hasChild("entropy298")) {
733  XML_Node& e298Node = e.child("entropy298");
734  if (e298Node.hasAttrib("value")) {
735  entropy298 = fpValueCheck(stripws(e298Node["value"]));
736  }
737  }
738  if (weight != 0.0) {
739  addUniqueElement(symbol, weight, anum, entropy298);
740  } else {
741  addUniqueElement(symbol);
742  }
743 }
744 
746 {
747  // get the declared element names
748  if (! phase.hasChild("elementArray")) {
749  throw CanteraError("Elements::addElementsFromXML",
750  "phase xml node doesn't have \"elementArray\" XML Node");
751  }
752  XML_Node& elements = phase.child("elementArray");
753  vector<string> enames;
754  ctml::getStringArray(elements, enames);
755 
756  // // element database defaults to elements.xml
757  string element_database = "elements.xml";
758  if (elements.hasAttrib("datasrc")) {
759  element_database = elements["datasrc"];
760  }
761 
762  XML_Node* doc = get_XML_File(element_database);
763  XML_Node* dbe = &doc->child("ctml/elementData");
764 
765  XML_Node& root = phase.root();
766  XML_Node* local_db = 0;
767  if (root.hasChild("ctml")) {
768  if (root.child("ctml").hasChild("elementData")) {
769  local_db = &root.child("ctml/elementData");
770  }
771  }
772 
773  int nel = static_cast<int>(enames.size());
774  int i;
775  string enm;
776  XML_Node* e = 0;
777  for (i = 0; i < nel; i++) {
778  e = 0;
779  if (local_db) {
780  //writelog("looking in local database.");
781  e = local_db->findByAttr("name",enames[i]);
782  //if (!e) writelog(enames[i]+" not found.");
783  }
784  if (!e) {
785  e = dbe->findByAttr("name",enames[i]);
786  }
787  if (e) {
788  addUniqueElement(*e);
789  } else {
790  throw CanteraError("addElementsFromXML","no data for element "
791  +enames[i]);
792  }
793  }
794 }
795 
797 {
798  m_elementsFrozen = true;
799 }
800 
802 {
803  return m_elementsFrozen;
804 }
805 
806 size_t Phase::addUniqueElementAfterFreeze(const std::string& symbol,
807  doublereal weight, int atomicNumber,
808  doublereal entropy298, int elem_type)
809 {
810  size_t ii = elementIndex(symbol);
811  if (ii != npos) {
812  return ii;
813  }
814  // Check to see that the element isn't really in the list
815  m_elementsFrozen = false;
816  addUniqueElement(symbol, weight, atomicNumber, entropy298, elem_type);
817  m_elementsFrozen = true;
818  ii = elementIndex(symbol);
819  if (ii != m_mm-1) {
820  throw CanteraError("Phase::addElementAfterFreeze()", "confused");
821  }
822  if (m_kk > 0) {
824  m_speciesComp.resize(m_kk*m_mm, 0.0);
825  for (size_t k = 0; k < m_kk; k++) {
826  size_t m_old = m_mm - 1;
827  for (size_t m = 0; m < m_old; m++) {
828  m_speciesComp[k * m_mm + m] = old[k * (m_old) + m];
829  }
830  m_speciesComp[k * (m_mm) + (m_mm-1)] = 0.0;
831  }
832  }
833  return ii;
834 }
835 
836 void Phase::addSpecies(const std::string& name_, const doublereal* comp,
837  doublereal charge_, doublereal size_)
838 {
839  freezeElements();
840  m_speciesNames.push_back(name_);
841  m_speciesCharge.push_back(charge_);
842  m_speciesSize.push_back(size_);
843  size_t ne = nElements();
844  // Create a changeable copy of the element composition. We now change
845  // the charge potentially
846  vector_fp compNew(ne);
847  for (size_t m = 0; m < ne; m++) {
848  compNew[m] = comp[m];
849  }
850  double wt = 0.0;
851  const vector_fp& aw = atomicWeights();
852  if (charge_ != 0.0) {
853  size_t eindex = elementIndex("E");
854  if (eindex != npos) {
855  doublereal ecomp = compNew[eindex];
856  if (fabs(charge_ + ecomp) > 0.001) {
857  if (ecomp != 0.0) {
858  throw CanteraError("Phase::addSpecies",
859  "Input charge and element E compositions differ "
860  "for species " + name_);
861  } else {
862  // Just fix up the element E composition based on the input
863  // species charge
864  compNew[eindex] = -charge_;
865  }
866  }
867  } else {
868  addUniqueElementAfterFreeze("E", 0.000545, 0, 0.0,
870  ne = nElements();
871  eindex = elementIndex("E");
872  compNew.resize(ne);
873  compNew[ne - 1] = - charge_;
874  }
875  }
876  for (size_t m = 0; m < ne; m++) {
877  m_speciesComp.push_back(compNew[m]);
878  wt += compNew[m] * aw[m];
879  }
880  m_molwts.push_back(wt);
881  m_kk++;
882 }
883 
884 void Phase::addUniqueSpecies(const std::string& name_, const doublereal* comp,
885  doublereal charge_, doublereal size_)
886 {
887  for (size_t k = 0; k < m_kk; k++) {
888  if (m_speciesNames[k] == name_) {
889  // We have found a match. Do some compatibility checks.
890  for (size_t i = 0; i < m_mm; i++) {
891  if (comp[i] != m_speciesComp[k * m_mm + i]) {
892  throw CanteraError("addUniqueSpecies",
893  "Duplicate species have different "
894  "compositions: " + name_);
895  }
896  }
897  if (charge_ != m_speciesCharge[k]) {
898  throw CanteraError("addUniqueSpecies",
899  "Duplicate species have different "
900  "charges: " + name_);
901  }
902  if (size_ != m_speciesSize[k]) {
903  throw CanteraError("addUniqueSpecies",
904  "Duplicate species have different "
905  "sizes: " + name_);
906  }
907  return;
908  }
909  }
910  addSpecies(name_, comp, charge_, size_);
911 }
912 
914 {
915  m_speciesFrozen = true;
917 }
918 
919 void Phase::init(const vector_fp& mw)
920 {
921  m_kk = mw.size();
922  m_rmolwts.resize(m_kk);
923  m_y.resize(m_kk, 0.0);
924  m_ym.resize(m_kk, 0.0);
925  copy(mw.begin(), mw.end(), m_molwts.begin());
926  for (size_t k = 0; k < m_kk; k++) {
927  if (m_molwts[k] < 0.0) {
928  throw CanteraError("Phase::init",
929  "negative molecular weight for species number "
930  + int2str(k));
931  }
932 
933  // Some surface phases may define species representing empty sites
934  // that have zero molecular weight. Give them a very small molecular
935  // weight to avoid dividing by zero.
936  if (m_molwts[k] < Tiny) {
937  m_molwts[k] = Tiny;
938  }
939  m_rmolwts[k] = 1.0/m_molwts[k];
940  }
941 
942  // Now that we have resized the State object, let's fill it with a valid
943  // mass fraction vector that sums to one. The Phase object should never
944  // have a mass fraction vector that doesn't sum to one. We will assume that
945  // species 0 has a mass fraction of 1.0 and mass fraction of all other
946  // species is 0.0.
947  m_y[0] = 1.0;
948  m_ym[0] = m_y[0] * m_rmolwts[0];
949  m_mmw = 1.0 / m_ym[0];
950 }
951 
952 bool Phase::ready() const
953 {
954  return (m_kk > 0 && m_elementsFrozen && m_speciesFrozen);
955 }
956 
957 } // namespace Cantera
Phase()
Default constructor.
Definition: Phase.cpp:18
std::map< std::string, doublereal > compositionMap
Map connecting a string name with a double.
Definition: ct_defs.h:162
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:215
virtual void setMoleFractions_NoNorm(const doublereal *const x)
Set the mole fractions to the specified values without normalizing.
Definition: Phase.cpp:344
XML_Node * findByAttr(const std::string &attr, const std::string &val, int depth=100000) const
This routine carries out a recursive search for an XML node based on an attribute of each XML node...
Definition: xml.cpp:716
doublereal molecularWeight(size_t k) const
Molecular weight of species k.
Definition: Phase.cpp:484
vector_fp m_y
species mass fractions
Definition: Phase.h:758
void setState_RY(doublereal rho, doublereal *y)
Set the density (kg/m^3) and mass fractions.
Definition: Phase.cpp:478
Array size error.
Definition: ctexceptions.h:123
std::vector< std::string > m_elementNames
element names
Definition: Phase.h:782
virtual doublereal density() const
Density (kg/m^3).
Definition: Phase.h:534
std::string int2str(const int n, const std::string &fmt)
Convert an int to a string using a format converter.
Definition: stringUtils.cpp:40
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:175
void restoreState(const vector_fp &state)
Restore a state saved on a previous call to saveState.
Definition: Phase.cpp:289
XML_Node * get_XML_File(const std::string &file, int debug)
Return a pointer to the XML tree for a Cantera input file.
Definition: global.cpp:144
bool m_elementsFrozen
If this is true, then no elements may be added to the object.
Definition: Phase.h:774
void setState_TRY(doublereal t, doublereal dens, const doublereal *y)
Set the internally stored temperature (K), density, and mass fractions.
Definition: Phase.cpp:440
size_t nElements() const
Number of elements.
Definition: Phase.cpp:139
vector_fp m_atomicWeights
element atomic weights (kg kmol-1)
Definition: Phase.h:780
void getMassFractions(doublereal *const y) const
Get the species mass fractions.
Definition: Phase.cpp:561
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:173
vector_fp m_speciesCharge
Vector of species charges. length m_kk.
Definition: Phase.h:731
Header file for class Phase.
vector_fp m_entropy298
Entropy at 298.15 K and 1 bar of stable state pure elements (J kmol-1)
Definition: Phase.h:786
doublereal atomicWeight(size_t m) const
Atomic weight of element m.
Definition: Phase.cpp:179
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:100
vector_fp m_speciesSize
Vector of species sizes.
Definition: Phase.h:729
doublereal m_mmw
mean molecular weight of the mixture (kg kmol-1)
Definition: Phase.h:752
Base class for phases of matter.
Definition: Phase.h:98
void addElement(const std::string &symbol, doublereal weight=-12345.0)
Add an element.
Definition: Phase.cpp:643
#define CT_ELEM_TYPE_ABSPOS
Normal element constraint consisting of positive coefficients for the formula matrix.
Definition: Elements.h:35
#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:597
void getMoleFractionsByName(compositionMap &x) const
Get the mole fractions by name.
Definition: Phase.cpp:510
Unary operator to multiply the argument by a constant.
Definition: utilities.h:30
void getMoleFractions(doublereal *const x) const
Get the species mole fraction vector.
Definition: Phase.cpp:519
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:144
void getConcentrations(doublereal *const c) const
Get the species concentrations (kmol/m^3).
Definition: Phase.cpp:572
std::string name() const
Return the name of the phase.
Definition: Phase.cpp:129
std::string m_name
Name of the phase.
Definition: Phase.h:743
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:151
doublereal concentration(const size_t k) const
Concentration of species k.
Definition: Phase.cpp:566
#define AssertThrowMsg(expr, procedure, message)
Assertion must be true or an error is thrown.
Definition: ctexceptions.h:247
doublereal sum_xlogQ(doublereal *const Q) const
Evaluate .
Definition: Phase.cpp:638
XML_Node & child(const size_t n) const
Return a changeable reference to the n'th child of the current node.
Definition: xml.cpp:584
doublereal entropyElement298(size_t m) const
Entropy of the element in its standard state at 298 K and 1 bar.
Definition: Phase.cpp:184
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:257
void setName(const std::string &nm)
Sets the string name for the phase.
Definition: Phase.cpp:134
doublereal mean_X(const doublereal *const Q) const
Evaluate the mole-fraction-weighted mean of an array Q.
Definition: Phase.cpp:623
const vector_fp & atomicWeights() const
Return a read-only reference to the vector of atomic weights.
Definition: Phase.cpp:193
void setMassFractionsByName(compositionMap &yMap)
Set the species mass fractions by name.
Definition: Phase.cpp:399
int m_stateNum
State Change variable.
Definition: Phase.h:766
size_t m_ndim
Dimensionality of the phase.
Definition: Phase.h:720
size_t speciesIndex(const std::string &name) const
Returns the index of a species named 'name' within the Phase object.
Definition: Phase.cpp:229
std::vector< std::string > m_speciesNames
Vector of the species names.
Definition: Phase.h:777
void setState_TRX(doublereal t, doublereal dens, const doublereal *x)
Set the internally stored temperature (K), density, and mole fractions.
Definition: Phase.cpp:419
void getAtoms(size_t k, double *atomArray) const
Get a vector containing the atomic composition of species k.
Definition: Phase.cpp:222
bool elementsFrozen()
True if freezeElements has been called.
Definition: Phase.cpp:801
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:673
doublereal molarVolume() const
Molar volume (m^3/kmol).
Definition: Phase.cpp:607
doublereal sum_xlogx() const
Evaluate .
Definition: Phase.cpp:633
int atomicNumber(size_t m) const
Atomic number of element m.
Definition: Phase.cpp:198
doublereal chargeDensity() const
Charge density [C/m^3].
Definition: Phase.cpp:612
const doublereal * massFractions() const
Return a const pointer to the mass fraction array.
Definition: Phase.h:454
std::string id() const
Return the string id for the phase.
Definition: Phase.cpp:119
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:68
doublereal sum_xlogQ(InputIter1 begin, InputIter1 end, InputIter2 Q_begin)
Compute .
Definition: utilities.h:552
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:426
void setMoleFractionsByName(compositionMap &xMap)
Set the species mole fractions by name.
Definition: Phase.cpp:354
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.
Exception class to indicate a fixed set of elements.
Definition: Elements.cpp:197
void addElementsFromXML(const XML_Node &phase)
Add all elements referenced in an XML_Node tree.
Definition: Phase.cpp:745
virtual void setConcentrations(const doublereal *const conc)
Set the concentrations to the specified values within the phase.
Definition: Phase.cpp:577
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:306
virtual ~Phase()
Destructor.
Definition: Phase.cpp:106
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:574
doublereal sum_xlogx(InputIter begin, InputIter end)
Compute .
Definition: utilities.h:524
const std::vector< std::string > & elementNames() const
Return a read-only reference to the vector of element names.
Definition: Phase.cpp:174
doublereal massFraction(size_t k) const
Return the mass fraction of a single species.
Definition: Phase.cpp:545
virtual void setMolarDensity(const doublereal molarDensity)
Set the internally stored molar density (kmol/m^3) of the phase.
Definition: Phase.cpp:602
virtual void freezeSpecies()
Call when finished adding species.
Definition: Phase.cpp:913
doublereal dot(InputIter x_begin, InputIter x_end, InputIter2 y_begin)
Function that calculates a templated inner product.
Definition: utilities.h:131
#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:388
size_t nSpecies() const
Returns the number of species in the phase.
Definition: Phase.h:252
void setState_TX(doublereal t, doublereal *x)
Set the internally stored temperature (K) and mole fractions.
Definition: Phase.cpp:460
vector_int m_elem_type
Vector of element types.
Definition: Phase.h:783
const std::vector< std::string > & speciesNames() const
Return a const reference to the vector of species names.
Definition: Phase.cpp:252
doublereal moleFraction(size_t k) const
Return the mole fraction of a single species.
Definition: Phase.cpp:524
const vector_fp & molecularWeights() const
Return a const reference to the internal vector of molecular weights.
Definition: Phase.cpp:505
bool m_speciesFrozen
Boolean indicating whether the number of species has been frozen.
Definition: Phase.h:771
#define AssertTrace(expr)
Assertion must be true or an error is thrown.
Definition: ctexceptions.h:216
doublereal temperature() const
Temperature (K).
Definition: Phase.h:528
void freezeElements()
Prohibit addition of more elements, and prepare to add species.
Definition: Phase.cpp:796
vector_fp m_molwts
species molecular weights (kg kmol-1)
Definition: Phase.h:760
void setState_TY(doublereal t, doublereal *y)
Set the internally stored temperature (K) and mass fractions.
Definition: Phase.cpp:466
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:165
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:264
size_t elementIndex(const std::string &name) const
Return the index of element named 'name'.
Definition: Phase.cpp:164
Templates for operations on vector-like objects.
Phase & operator=(const Phase &right)
Assignment operator.
Definition: Phase.cpp:54
size_t m_mm
Number of elements.
Definition: Phase.h:779
void getStringArray(const Cantera::XML_Node &node, std::vector< std::string > &v)
This function interprets the value portion of an XML element as a string.
Definition: ctml.cpp:639
virtual void setTemperature(const doublereal temp)
Set the internally stored temperature of the phase (K).
Definition: Phase.h:562
void scale(InputIter begin, InputIter end, OutputIter out, S scale_factor)
Multiply elements of an array by a scale factor.
Definition: utilities.h:154
const doublereal Tiny
Small number to compare differences of mole fractions against.
Definition: ct_defs.h:155
std::string m_id
ID of the phase.
Definition: Phase.h:738
doublereal m_dens
Density (kg m-3).
Definition: Phase.h:750
vector_fp m_ym
m_ym[k] = mole fraction of species k divided by the mean molecular weight of mixture.
Definition: Phase.h:756
doublereal meanMolecularWeight() const
The mean molecular weight. Units: (kg/kmol)
Definition: Phase.h:588
XML_Node * m_xml
XML node containing the XML info for this phase.
Definition: Phase.h:734
vector_int m_atomicNumbers
element atomic numbers
Definition: Phase.h:781
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:271
void getMolecularWeights(vector_fp &weights) const
Copy the vector of molecular weights into vector weights.
Definition: Phase.cpp:490
std::string elementName(size_t m) const
Name of the element with index m.
Definition: Phase.cpp:158
doublereal m_temp
Temperature (K). This is an independent variable.
Definition: Phase.h:745
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:277
XML_Node & xml()
Returns a reference to the XML_Node stored for the phase.
Definition: Phase.cpp:114
virtual void setMassFractions(const doublereal *const y)
Set the mass fractions to the specified values and normalize them.
Definition: Phase.cpp:374
int elementType(size_t m) const
Return the element constraint type Possible types include:
Definition: Phase.cpp:203
void init(const vector_fp &mw)
Definition: Phase.cpp:919
vector_fp m_rmolwts
inverse of species molecular weights (kmol kg-1)
Definition: Phase.h:762
vector_fp m_speciesComp
Atomic composition of the species.
Definition: Phase.h:725
void setState_RX(doublereal rho, doublereal *x)
Set the density (kg/m^3) and mole fractions.
Definition: Phase.cpp:472
size_t m_kk
Number of species in the phase.
Definition: Phase.h:716
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:806
An array index is out of range.
Definition: ctexceptions.h:153
int changeElementType(int m, int elem_type)
Change the element type of the mth constraint Reassigns an element type.
Definition: Phase.cpp:208
void setID(const std::string &id)
Set the string id for the phase.
Definition: Phase.cpp:124
XML_Node & root() const
Return the root of the current XML_Node tree.
Definition: xml.cpp:1091
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:454
std::string speciesName(size_t k) const
Name of the species with index k.
Definition: Phase.cpp:246
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:884
const doublereal * moleFractdivMMW() const
Returns a const pointer to the start of the moleFraction/MW array.
Definition: Phase.cpp:540
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...
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:549
doublereal mean_Y(const doublereal *const Q) const
Evaluate the mass-fraction-weighted mean of an array Q.
Definition: Phase.cpp:628
bool hasAttrib(const std::string &a) const
Tests whether the current node has an attribute with a particular name.
Definition: xml.cpp:579
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:504