Cantera  2.3.0
LatticeSolidPhase.cpp
Go to the documentation of this file.
1 /**
2  * @file LatticeSolidPhase.cpp
3  * Definitions for a simple thermodynamics model of a bulk solid phase
4  * derived from ThermoPhase,
5  * assuming an ideal solution model based on a lattice of solid atoms
6  * (see \ref thermoprops and class \link Cantera::LatticeSolidPhase LatticeSolidPhase\endlink).
7  */
8 
9 // This file is part of Cantera. See License.txt in the top-level directory or
10 // at http://www.cantera.org/license.txt for license and copyright information.
11 
16 #include "cantera/base/ctml.h"
18 #include "cantera/base/utilities.h"
19 
20 using namespace std;
21 
22 namespace Cantera
23 {
24 LatticeSolidPhase::LatticeSolidPhase() :
25  m_press(-1.0),
26  m_molar_density(0.0)
27 {
28 }
29 
31  m_press(-1.0),
32  m_molar_density(0.0)
33 {
34  *this = right;
35 }
36 
37 LatticeSolidPhase& LatticeSolidPhase::operator=(const LatticeSolidPhase& right)
38 {
39  if (&right != this) {
41  m_tlast = right.m_tlast;
42  m_press = right.m_press;
43  m_molar_density = right.m_molar_density;
44  deepStdVectorPointerCopy<LatticePhase>(right.m_lattice, m_lattice);
45  m_x = right.m_x;
46  theta_ = right.theta_;
47  tmpV_ = right.tmpV_;
48  }
49  return *this;
50 }
51 
52 LatticeSolidPhase::~LatticeSolidPhase()
53 {
54  // We own the sublattices. So we have to delete the sublattices
55  for (size_t n = 0; n < m_lattice.size(); n++) {
56  delete m_lattice[n];
57  m_lattice[n] = 0;
58  }
59 }
60 
62 {
63  return new LatticeSolidPhase(*this);
64 }
65 
66 doublereal LatticeSolidPhase::minTemp(size_t k) const
67 {
68  if (k != npos) {
69  for (size_t n = 0; n < m_lattice.size(); n++) {
70  if (lkstart_[n+1] < k) {
71  return m_lattice[n]->minTemp(k-lkstart_[n]);
72  }
73  }
74  }
75  doublereal mm = 1.0E300;
76  for (size_t n = 0; n < m_lattice.size(); n++) {
77  double ml = m_lattice[n]->minTemp();
78  mm = std::min(mm, ml);
79  }
80  return mm;
81 }
82 
83 doublereal LatticeSolidPhase::maxTemp(size_t k) const
84 {
85  if (k != npos) {
86  for (size_t n = 0; n < m_lattice.size(); n++) {
87  if (lkstart_[n+1] < k) {
88  return (m_lattice[n])->maxTemp(k - lkstart_[n]);
89  }
90  }
91  }
92  doublereal mm = -1.0E300;
93  for (size_t n = 0; n < m_lattice.size(); n++) {
94  double ml = m_lattice[n]->maxTemp();
95  mm = std::max(mm, ml);
96  }
97  return mm;
98 }
99 
101 {
102  return m_lattice[0]->refPressure();
103 }
104 
106 {
107  _updateThermo();
108  doublereal sum = 0.0;
109  for (size_t n = 0; n < m_lattice.size(); n++) {
110  sum += theta_[n] * m_lattice[n]->enthalpy_mole();
111  }
112  return sum;
113 }
114 
116 {
117  _updateThermo();
118  doublereal sum = 0.0;
119  for (size_t n = 0; n < m_lattice.size(); n++) {
120  sum += theta_[n] * m_lattice[n]->intEnergy_mole();
121  }
122  return sum;
123 }
124 
126 {
127  _updateThermo();
128  doublereal sum = 0.0;
129  for (size_t n = 0; n < m_lattice.size(); n++) {
130  sum += theta_[n] * m_lattice[n]->entropy_mole();
131  }
132  return sum;
133 }
134 
136 {
137  _updateThermo();
138  doublereal sum = 0.0;
139  for (size_t n = 0; n < m_lattice.size(); n++) {
140  sum += theta_[n] * m_lattice[n]->gibbs_mole();
141  }
142  return sum;
143 }
144 
145 doublereal LatticeSolidPhase::cp_mole() const
146 {
147  _updateThermo();
148  doublereal sum = 0.0;
149  for (size_t n = 0; n < m_lattice.size(); n++) {
150  sum += theta_[n] * m_lattice[n]->cp_mole();
151  }
152  return sum;
153 }
154 
156 {
157  _updateThermo();
158  size_t strt = 0;
159  for (size_t n = 0; n < m_lattice.size(); n++) {
160  m_lattice[n]->getMoleFractions(c+strt);
161  strt += m_lattice[n]->nSpecies();
162  }
163 }
164 
166 {
167  for (size_t k = 0; k < m_kk; k++) {
168  ac[k] = 1.0;
169  }
170 }
171 
173 {
174  return 1.0;
175 }
176 
177 doublereal LatticeSolidPhase::logStandardConc(size_t k) const
178 {
179  return 0.0;
180 }
181 
183 {
184  m_press = p;
185  for (size_t n = 0; n < m_lattice.size(); n++) {
186  m_lattice[n]->setPressure(m_press);
187  }
188  calcDensity();
189 }
190 
192 {
193  double sum = 0.0;
194  for (size_t n = 0; n < m_lattice.size(); n++) {
195  sum += theta_[n] * m_lattice[n]->density();
196  }
197  Phase::setDensity(sum);
198  return sum;
199 }
200 
201 void LatticeSolidPhase::setMoleFractions(const doublereal* const x)
202 {
203  size_t strt = 0;
204  for (size_t n = 0; n < m_lattice.size(); n++) {
205  size_t nsp = m_lattice[n]->nSpecies();
206  m_lattice[n]->setMoleFractions(x + strt);
207  strt += nsp;
208  }
209  for (size_t k = 0; k < strt; k++) {
210  m_x[k] = x[k] / m_lattice.size();
211  }
213  calcDensity();
214 }
215 
216 void LatticeSolidPhase::getMoleFractions(doublereal* const x) const
217 {
218  size_t strt = 0;
219  // the ifdef block should be the way we calculate this.!!!!!
221  for (size_t n = 0; n < m_lattice.size(); n++) {
222  size_t nsp = m_lattice[n]->nSpecies();
223  double sum = 0.0;
224  for (size_t k = 0; k < nsp; k++) {
225  sum += (x + strt)[k];
226  }
227  for (size_t k = 0; k < nsp; k++) {
228  (x + strt)[k] /= sum;
229  }
230 
231  // At this point we can check against the mole fraction vector of the
232  // underlying LatticePhase objects and get the same answer.
233  m_lattice[n]->getMoleFractions(&m_x[strt]);
234  for (size_t k = 0; k < nsp; k++) {
235  if (fabs((x + strt)[k] - m_x[strt+k]) > 1.0E-14) {
236  throw CanteraError("LatticeSolidPhase::getMoleFractions()",
237  "internal error");
238  }
239  }
240  strt += nsp;
241  }
242 }
243 
244 void LatticeSolidPhase::getChemPotentials(doublereal* mu) const
245 {
246  _updateThermo();
247  size_t strt = 0;
248  for (size_t n = 0; n < m_lattice.size(); n++) {
249  size_t nlsp = m_lattice[n]->nSpecies();
250  m_lattice[n]->getChemPotentials(mu+strt);
251  strt += nlsp;
252  }
253 }
254 
256 {
257  _updateThermo();
258  size_t strt = 0;
259  for (size_t n = 0; n < m_lattice.size(); n++) {
260  size_t nlsp = m_lattice[n]->nSpecies();
261  m_lattice[n]->getPartialMolarEnthalpies(hbar + strt);
262  strt += nlsp;
263  }
264 }
265 
267 {
268  _updateThermo();
269  size_t strt = 0;
270  for (size_t n = 0; n < m_lattice.size(); n++) {
271  size_t nlsp = m_lattice[n]->nSpecies();
272  m_lattice[n]->getPartialMolarEntropies(sbar + strt);
273  strt += nlsp;
274  }
275 }
276 
277 void LatticeSolidPhase::getPartialMolarCp(doublereal* cpbar) const
278 {
279  _updateThermo();
280  size_t strt = 0;
281  for (size_t n = 0; n < m_lattice.size(); n++) {
282  size_t nlsp = m_lattice[n]->nSpecies();
283  m_lattice[n]->getPartialMolarCp(cpbar + strt);
284  strt += nlsp;
285  }
286 }
287 
288 void LatticeSolidPhase::getPartialMolarVolumes(doublereal* vbar) const
289 {
290  _updateThermo();
291  size_t strt = 0;
292  for (size_t n = 0; n < m_lattice.size(); n++) {
293  size_t nlsp = m_lattice[n]->nSpecies();
294  m_lattice[n]->getPartialMolarVolumes(vbar + strt);
295  strt += nlsp;
296  }
297 }
298 
300 {
301  _updateThermo();
302  size_t strt = 0;
303  for (size_t n = 0; n < m_lattice.size(); n++) {
304  m_lattice[n]->getStandardChemPotentials(mu0+strt);
305  strt += m_lattice[n]->nSpecies();
306  }
307 }
308 
309 void LatticeSolidPhase::getGibbs_RT_ref(doublereal* grt) const
310 {
311  _updateThermo();
312  for (size_t n = 0; n < m_lattice.size(); n++) {
313  m_lattice[n]->getGibbs_RT_ref(grt + lkstart_[n]);
314  }
315 }
316 
317 void LatticeSolidPhase::getGibbs_ref(doublereal* g) const
318 {
319  getGibbs_RT_ref(g);
320  for (size_t k = 0; k < m_kk; k++) {
321  g[k] *= RT();
322  }
323 }
324 
326 {
327  size_t kk = 0;
328  size_t kstart = 0;
329  lkstart_.resize(m_lattice.size() + 1);
330  size_t loc = 0;
331 
332  for (size_t n = 0; n < m_lattice.size(); n++) {
333  LatticePhase* lp = m_lattice[n];
334  vector_fp constArr(lp->nElements());
335  const vector_fp& aws = lp->atomicWeights();
336  for (size_t es = 0; es < lp->nElements(); es++) {
337  addElement(lp->elementName(es), aws[es], lp->atomicNumber(es),
338  lp->entropyElement298(es), lp->elementType(es));
339  }
340  kstart = kk;
341 
342  for (size_t k = 0; k < lp->nSpecies(); k++) {
343  addSpecies(lp->species(k));
344  kk++;
345  }
346  // Add in the lattice stoichiometry constraint
347  if (n > 0) {
348  string econ = fmt::format("LC_{}_{}", n, id());
349  size_t m = addElement(econ, 0.0, 0, 0.0, CT_ELEM_TYPE_LATTICERATIO);
350  size_t mm = nElements();
351  size_t nsp0 = m_lattice[0]->nSpecies();
352  for (size_t k = 0; k < nsp0; k++) {
353  m_speciesComp[k * mm + m] = -theta_[0];
354  }
355  for (size_t k = 0; k < lp->nSpecies(); k++) {
356  size_t ks = kstart + k;
357  m_speciesComp[ks * mm + m] = theta_[n];
358  }
359  }
360  size_t nsp = m_lattice[n]->nSpecies();
361  lkstart_[n] = loc;
362  for (size_t k = 0; k < nsp; k++) {
363  m_x[loc] =m_lattice[n]->moleFraction(k) / (double) m_lattice.size();
364  loc++;
365  }
366  lkstart_[n+1] = loc;
367  }
368 
369  setMoleFractions(m_x.data());
371 }
372 
373 bool LatticeSolidPhase::addSpecies(shared_ptr<Species> spec)
374 {
375  bool added = ThermoPhase::addSpecies(spec);
376  if (added) {
377  m_x.push_back(0.0);
378  tmpV_.push_back(0.0);
379  }
380  return added;
381 }
382 
384 {
385  doublereal tnow = temperature();
386  if (m_tlast != tnow) {
387  getMoleFractions(m_x.data());
388  size_t strt = 0;
389  for (size_t n = 0; n < m_lattice.size(); n++) {
390  m_lattice[n]->setTemperature(tnow);
391  m_lattice[n]->setMoleFractions(&m_x[strt]);
392  m_lattice[n]->setPressure(m_press);
393  strt += m_lattice[n]->nSpecies();
394  }
395  m_tlast = tnow;
396  }
397 }
398 
399 void LatticeSolidPhase::setLatticeMoleFractionsByName(int nn, const std::string& x)
400 {
401  m_lattice[nn]->setMoleFractionsByName(x);
402  size_t loc = 0;
403  for (size_t n = 0; n < m_lattice.size(); n++) {
404  size_t nsp = m_lattice[n]->nSpecies();
405  double ndens = m_lattice[n]->molarDensity();
406  for (size_t k = 0; k < nsp; k++) {
407  m_x[loc] = ndens * m_lattice[n]->moleFraction(k);
408  loc++;
409  }
410  }
411  setMoleFractions(m_x.data());
412 }
413 
415 {
416  eosdata._require("model","LatticeSolid");
417  XML_Node& la = eosdata.child("LatticeArray");
418  std::vector<XML_Node*> lattices = la.getChildren("phase");
419  for (size_t n = 0; n < lattices.size(); n++) {
420  m_lattice.push_back((LatticePhase*)newPhase(*lattices[n]));
421  }
422  std::vector<string> pnam;
423  std::vector<string> pval;
424  int np = getPairs(eosdata.child("LatticeStoichiometry"), pnam, pval);
425  theta_.resize(m_lattice.size());
426  for (int i = 0; i < np; i++) {
427  double val = fpValueCheck(pval[i]);
428  bool found = false;
429  for (size_t j = 0; j < m_lattice.size(); j++) {
430  ThermoPhase& tp = *m_lattice[j];
431  string idj = tp.id();
432  if (idj == pnam[i]) {
433  theta_[j] = val;
434  found = true;
435  break;
436  }
437  }
438  if (!found) {
439  throw CanteraError("LatticeSolidPhase::setParametersFromXML", "not found");
440  }
441  }
442 }
443 
444 void LatticeSolidPhase::modifyOneHf298SS(const size_t k, const doublereal Hf298New)
445 {
446  for (size_t n = 0; n < m_lattice.size(); n++) {
447  if (lkstart_[n+1] < k) {
448  size_t kk = k-lkstart_[n];
449  MultiSpeciesThermo& l_spthermo = m_lattice[n]->speciesThermo();
450  l_spthermo.modifyOneHf298(kk, Hf298New);
451  }
452  }
453  invalidateCache();
454  _updateThermo();
455 }
456 
457 void LatticeSolidPhase::resetHf298(const size_t k)
458 {
459  if (k != npos) {
460  for (size_t n = 0; n < m_lattice.size(); n++) {
461  if (lkstart_[n+1] < k) {
462  size_t kk = k-lkstart_[n];
463  m_lattice[n]->speciesThermo().resetHf298(kk);
464  }
465  }
466  } else {
467  for (size_t n = 0; n < m_lattice.size(); n++) {
468  m_lattice[n]->speciesThermo().resetHf298(npos);
469  }
470  }
471  invalidateCache();
472  _updateThermo();
473 }
474 
475 } // End namespace Cantera
Header for a general species thermodynamic property manager for a phase (see MultiSpeciesThermo).
std::vector< XML_Node * > getChildren(const std::string &name) const
Get a vector of pointers to XML_Node containing all of the children of the current node which match t...
Definition: xml.cpp:864
ThermoPhase * newPhase(XML_Node &xmlphase)
Create a new ThermoPhase object and initializes it according to the XML tree.
virtual void getGibbs_RT_ref(doublereal *grt) const
Returns the vector of nondimensional Gibbs Free Energies of the reference state at the current temper...
virtual void modifyOneHf298SS(const size_t k, const doublereal Hf298New)
Modify the value of the 298 K Heat of Formation of one species in the phase (J kmol-1) ...
size_t nElements() const
Number of elements.
Definition: Phase.cpp:161
virtual bool addSpecies(shared_ptr< Species > spec)
virtual void getPartialMolarEntropies(doublereal *sbar) const
Returns an array of partial molar entropies of the species in the solution.
virtual void getMoleFractions(doublereal *const x) const
Get the species mole fraction vector.
virtual doublereal logStandardConc(size_t k=0) const
Natural logarithm of the standard concentration of the kth species.
std::vector< LatticePhase * > m_lattice
Vector of sublattic ThermoPhase objects.
CTML ("Cantera Markup Language") is the variant of XML that Cantera uses to store data...
virtual void initThermo()
Initialize the ThermoPhase object after all species have been set up.
doublereal temperature() const
Temperature (K).
Definition: Phase.h:601
Various templated functions that carry out common vector operations (see Templated Utility Functions)...
virtual void modifyOneHf298(const size_t k, const doublereal Hf298New)
Modify the value of the 298 K Heat of Formation of the standard state of one species in the phase (J ...
doublereal calcDensity()
Calculate the density of the solid mixture.
virtual void initThermo()
Initialize the ThermoPhase object after all species have been set up.
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:165
vector_fp theta_
Lattice stoichiometric coefficients.
ThermoPhase & operator=(const ThermoPhase &right)
Definition: ThermoPhase.cpp:59
Headers for the factory class that can create known ThermoPhase objects (see Thermodynamic Properties...
LatticeSolidPhase()
Base empty constructor.
virtual void getGibbs_ref(doublereal *g) const
Returns the vector of the Gibbs function of the reference state at the current temperature of the sol...
virtual void setMoleFractions(const doublereal *const x)
Set the mole fractions to the specified values, and then normalize them so that they sum to 1...
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:97
size_t nSpecies() const
Returns the number of species in the phase.
Definition: Phase.h:262
STL namespace.
virtual void getPartialMolarCp(doublereal *cpbar) const
Returns an array of partial molar Heat Capacities at constant pressure of the species in the solution...
virtual doublereal intEnergy_mole() const
Return the Molar Internal Energy. Units: J/kmol.
A simple thermodynamic model for a bulk phase, assuming a lattice of solid atoms. ...
Definition: LatticePhase.h:232
virtual void getPartialMolarEnthalpies(doublereal *hbar) const
Returns an array of partial molar enthalpies for the species in the mixture.
doublereal m_tlast
last value of the temperature processed by reference state
Definition: ThermoPhase.h:1737
virtual ThermoPhase * duplMyselfAsThermoPhase() const
Duplication routine for objects which inherit from ThermoPhase.
virtual void setPressure(doublereal p)
Set the pressure at constant temperature. Units: Pa.
doublereal RT() const
Return the Gas Constant multiplied by the current temperature.
Definition: ThermoPhase.h:809
Base class for a phase with thermodynamic properties.
Definition: ThermoPhase.h:93
virtual doublereal standardConcentration(size_t k=0) const
Return the standard concentration for the kth species.
int atomicNumber(size_t m) const
Atomic number of element m.
Definition: Phase.cpp:220
virtual void invalidateCache()
Invalidate any cached values which are normally updated only when a change in state is detected...
void _updateThermo() const
Update the reference thermodynamic functions.
void _require(const std::string &a, const std::string &v) const
Require that the current XML node have an attribute named by the first argument, a, and that this attribute have the the string value listed in the second argument, v.
Definition: xml.cpp:576
Header for a simple thermodynamics model of a bulk solid phase derived from ThermoPhase, assuming an ideal solution model based on a lattice of solid atoms (see Thermodynamic Properties and class LatticeSolidPhase).
shared_ptr< Species > species(const std::string &name) const
Return the Species object for the named species.
Definition: Phase.cpp:868
virtual void resetHf298(const size_t k=npos)
Restore the original heat of formation of one or more species.
doublereal m_molar_density
Current value of the molar density.
virtual void getChemPotentials(doublereal *mu) const
Get the species chemical potentials. Units: J/kmol.
vector_fp tmpV_
Temporary vector.
doublereal entropyElement298(size_t m) const
Entropy of the element in its standard state at 298 K and 1 bar.
Definition: Phase.cpp:206
virtual void getActivityCoefficients(doublereal *ac) const
Get the array of non-dimensional molar-based activity coefficients at the current solution temperatur...
int getPairs(const XML_Node &node, std::vector< std::string > &key, std::vector< std::string > &val)
This function interprets the value portion of an XML element as a series of "Pairs" separated by whit...
Definition: ctml.cpp:387
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:65
doublereal m_press
Current value of the pressure.
virtual doublereal entropy_mole() const
Return the Molar Entropy. Units: J/kmol/K.
virtual void setMoleFractions(const doublereal *const x)
Set the mole fractions to the specified values.
Definition: Phase.cpp:327
void getMoleFractions(doublereal *const x) const
Get the species mole fraction vector.
Definition: Phase.cpp:542
void setLatticeMoleFractionsByName(int n, const std::string &x)
Set the Lattice mole fractions using a string.
virtual void getActivityConcentrations(doublereal *c) const
This method returns an array of generalized concentrations.
XML_Node & child(const size_t n) const
Return a changeable reference to the n&#39;th child of the current node.
Definition: xml.cpp:546
vector_fp m_x
Vector of mole fractions.
Header for factory functions to build instances of classes that manage the standard-state thermodynam...
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
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
virtual void setParametersFromXML(const XML_Node &eosdata)
Set equation of state parameter values from XML entries.
int elementType(size_t m) const
Return the element constraint type Possible types include:
Definition: Phase.cpp:225
A phase that is comprised of a fixed additive combination of other lattice phases.
virtual bool addSpecies(shared_ptr< Species > spec)
virtual doublereal maxTemp(size_t k=npos) const
Maximum temperature for which the thermodynamic data for the species are valid.
Contains declarations for string manipulation functions within Cantera.
virtual doublereal refPressure() const
Returns the reference pressure in Pa.
virtual doublereal minTemp(size_t k=npos) const
Minimum temperature for which the thermodynamic data for the species or phase are valid...
vector_fp m_speciesComp
Atomic composition of the species.
Definition: Phase.h:793
#define CT_ELEM_TYPE_LATTICERATIO
Constraint associated with maintaining a fixed lattice stoichiometry in a solid.
Definition: Elements.h:56
size_t m_kk
Number of species in the phase.
Definition: Phase.h:784
virtual void getPartialMolarVolumes(doublereal *vbar) const
returns an array of partial molar volumes of the species in the solution.
A species thermodynamic property manager for a phase.
Namespace for the Cantera kernel.
Definition: application.cpp:29
virtual doublereal cp_mole() const
Return the constant pressure heat capacity. Units: J/kmol/K.
virtual void getStandardChemPotentials(doublereal *mu0) const
Get the array of standard state chemical potentials at unit activity for the species at their standar...
doublereal fpValueCheck(const std::string &val)
Translate a string into one doublereal value, with error checking.
virtual doublereal enthalpy_mole() const
Return the Molar Enthalpy. Units: J/kmol.
const vector_fp & atomicWeights() const
Return a read-only reference to the vector of atomic weights.
Definition: Phase.cpp:215
virtual doublereal gibbs_mole() const
Return the Molar Gibbs energy. Units: J/kmol.
std::string elementName(size_t m) const
Name of the element with index m.
Definition: Phase.cpp:180
virtual void setDensity(const doublereal density_)
Set the internally stored density (kg/m^3) of the phase.
Definition: Phase.h:622