Cantera  2.4.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 
30 doublereal LatticeSolidPhase::minTemp(size_t k) const
31 {
32  if (k != npos) {
33  for (size_t n = 0; n < m_lattice.size(); n++) {
34  if (lkstart_[n+1] < k) {
35  return m_lattice[n]->minTemp(k-lkstart_[n]);
36  }
37  }
38  }
39  doublereal mm = 1.0E300;
40  for (size_t n = 0; n < m_lattice.size(); n++) {
41  double ml = m_lattice[n]->minTemp();
42  mm = std::min(mm, ml);
43  }
44  return mm;
45 }
46 
47 doublereal LatticeSolidPhase::maxTemp(size_t k) const
48 {
49  if (k != npos) {
50  for (size_t n = 0; n < m_lattice.size(); n++) {
51  if (lkstart_[n+1] < k) {
52  return (m_lattice[n])->maxTemp(k - lkstart_[n]);
53  }
54  }
55  }
56  doublereal mm = -1.0E300;
57  for (size_t n = 0; n < m_lattice.size(); n++) {
58  double ml = m_lattice[n]->maxTemp();
59  mm = std::max(mm, ml);
60  }
61  return mm;
62 }
63 
65 {
66  return m_lattice[0]->refPressure();
67 }
68 
70 {
71  _updateThermo();
72  doublereal sum = 0.0;
73  for (size_t n = 0; n < m_lattice.size(); n++) {
74  sum += theta_[n] * m_lattice[n]->enthalpy_mole();
75  }
76  return sum;
77 }
78 
80 {
81  _updateThermo();
82  doublereal sum = 0.0;
83  for (size_t n = 0; n < m_lattice.size(); n++) {
84  sum += theta_[n] * m_lattice[n]->intEnergy_mole();
85  }
86  return sum;
87 }
88 
90 {
91  _updateThermo();
92  doublereal sum = 0.0;
93  for (size_t n = 0; n < m_lattice.size(); n++) {
94  sum += theta_[n] * m_lattice[n]->entropy_mole();
95  }
96  return sum;
97 }
98 
100 {
101  _updateThermo();
102  doublereal sum = 0.0;
103  for (size_t n = 0; n < m_lattice.size(); n++) {
104  sum += theta_[n] * m_lattice[n]->gibbs_mole();
105  }
106  return sum;
107 }
108 
109 doublereal LatticeSolidPhase::cp_mole() const
110 {
111  _updateThermo();
112  doublereal sum = 0.0;
113  for (size_t n = 0; n < m_lattice.size(); n++) {
114  sum += theta_[n] * m_lattice[n]->cp_mole();
115  }
116  return sum;
117 }
118 
120 {
121  _updateThermo();
122  size_t strt = 0;
123  for (size_t n = 0; n < m_lattice.size(); n++) {
124  m_lattice[n]->getMoleFractions(c+strt);
125  strt += m_lattice[n]->nSpecies();
126  }
127 }
128 
130 {
131  for (size_t k = 0; k < m_kk; k++) {
132  ac[k] = 1.0;
133  }
134 }
135 
137 {
138  return 1.0;
139 }
140 
141 doublereal LatticeSolidPhase::logStandardConc(size_t k) const
142 {
143  return 0.0;
144 }
145 
147 {
148  m_press = p;
149  for (size_t n = 0; n < m_lattice.size(); n++) {
150  m_lattice[n]->setPressure(m_press);
151  }
152  calcDensity();
153 }
154 
156 {
157  double sum = 0.0;
158  for (size_t n = 0; n < m_lattice.size(); n++) {
159  sum += theta_[n] * m_lattice[n]->density();
160  }
161  Phase::setDensity(sum);
162  return sum;
163 }
164 
165 void LatticeSolidPhase::setMoleFractions(const doublereal* const x)
166 {
167  size_t strt = 0;
168  for (size_t n = 0; n < m_lattice.size(); n++) {
169  size_t nsp = m_lattice[n]->nSpecies();
170  m_lattice[n]->setMoleFractions(x + strt);
171  strt += nsp;
172  }
173  for (size_t k = 0; k < strt; k++) {
174  m_x[k] = x[k] / m_lattice.size();
175  }
177  calcDensity();
178 }
179 
180 void LatticeSolidPhase::getMoleFractions(doublereal* const x) const
181 {
182  size_t strt = 0;
183  // the ifdef block should be the way we calculate this.!!!!!
185  for (size_t n = 0; n < m_lattice.size(); n++) {
186  size_t nsp = m_lattice[n]->nSpecies();
187  double sum = 0.0;
188  for (size_t k = 0; k < nsp; k++) {
189  sum += (x + strt)[k];
190  }
191  for (size_t k = 0; k < nsp; k++) {
192  (x + strt)[k] /= sum;
193  }
194 
195  // At this point we can check against the mole fraction vector of the
196  // underlying LatticePhase objects and get the same answer.
197  m_lattice[n]->getMoleFractions(&m_x[strt]);
198  for (size_t k = 0; k < nsp; k++) {
199  if (fabs((x + strt)[k] - m_x[strt+k]) > 1.0E-14) {
200  throw CanteraError("LatticeSolidPhase::getMoleFractions()",
201  "internal error");
202  }
203  }
204  strt += nsp;
205  }
206 }
207 
208 void LatticeSolidPhase::getChemPotentials(doublereal* mu) const
209 {
210  _updateThermo();
211  size_t strt = 0;
212  for (size_t n = 0; n < m_lattice.size(); n++) {
213  size_t nlsp = m_lattice[n]->nSpecies();
214  m_lattice[n]->getChemPotentials(mu+strt);
215  strt += nlsp;
216  }
217 }
218 
220 {
221  _updateThermo();
222  size_t strt = 0;
223  for (size_t n = 0; n < m_lattice.size(); n++) {
224  size_t nlsp = m_lattice[n]->nSpecies();
225  m_lattice[n]->getPartialMolarEnthalpies(hbar + strt);
226  strt += nlsp;
227  }
228 }
229 
231 {
232  _updateThermo();
233  size_t strt = 0;
234  for (size_t n = 0; n < m_lattice.size(); n++) {
235  size_t nlsp = m_lattice[n]->nSpecies();
236  m_lattice[n]->getPartialMolarEntropies(sbar + strt);
237  strt += nlsp;
238  }
239 }
240 
241 void LatticeSolidPhase::getPartialMolarCp(doublereal* cpbar) const
242 {
243  _updateThermo();
244  size_t strt = 0;
245  for (size_t n = 0; n < m_lattice.size(); n++) {
246  size_t nlsp = m_lattice[n]->nSpecies();
247  m_lattice[n]->getPartialMolarCp(cpbar + strt);
248  strt += nlsp;
249  }
250 }
251 
252 void LatticeSolidPhase::getPartialMolarVolumes(doublereal* vbar) const
253 {
254  _updateThermo();
255  size_t strt = 0;
256  for (size_t n = 0; n < m_lattice.size(); n++) {
257  size_t nlsp = m_lattice[n]->nSpecies();
258  m_lattice[n]->getPartialMolarVolumes(vbar + strt);
259  strt += nlsp;
260  }
261 }
262 
264 {
265  _updateThermo();
266  size_t strt = 0;
267  for (size_t n = 0; n < m_lattice.size(); n++) {
268  m_lattice[n]->getStandardChemPotentials(mu0+strt);
269  strt += m_lattice[n]->nSpecies();
270  }
271 }
272 
273 void LatticeSolidPhase::getGibbs_RT_ref(doublereal* grt) const
274 {
275  _updateThermo();
276  for (size_t n = 0; n < m_lattice.size(); n++) {
277  m_lattice[n]->getGibbs_RT_ref(grt + lkstart_[n]);
278  }
279 }
280 
281 void LatticeSolidPhase::getGibbs_ref(doublereal* g) const
282 {
283  getGibbs_RT_ref(g);
284  for (size_t k = 0; k < m_kk; k++) {
285  g[k] *= RT();
286  }
287 }
288 
290 {
291  size_t kk = 0;
292  size_t kstart = 0;
293  lkstart_.resize(m_lattice.size() + 1);
294  size_t loc = 0;
295 
296  for (size_t n = 0; n < m_lattice.size(); n++) {
297  shared_ptr<ThermoPhase>& lp = m_lattice[n];
298  vector_fp constArr(lp->nElements());
299  const vector_fp& aws = lp->atomicWeights();
300  for (size_t es = 0; es < lp->nElements(); es++) {
301  addElement(lp->elementName(es), aws[es], lp->atomicNumber(es),
302  lp->entropyElement298(es), lp->elementType(es));
303  }
304  kstart = kk;
305 
306  for (size_t k = 0; k < lp->nSpecies(); k++) {
307  addSpecies(lp->species(k));
308  kk++;
309  }
310  // Add in the lattice stoichiometry constraint
311  if (n > 0) {
312  string econ = fmt::format("LC_{}_{}", n, id());
313  size_t m = addElement(econ, 0.0, 0, 0.0, CT_ELEM_TYPE_LATTICERATIO);
314  size_t mm = nElements();
315  size_t nsp0 = m_lattice[0]->nSpecies();
316  for (size_t k = 0; k < nsp0; k++) {
317  m_speciesComp[k * mm + m] = -theta_[0];
318  }
319  for (size_t k = 0; k < lp->nSpecies(); k++) {
320  size_t ks = kstart + k;
321  m_speciesComp[ks * mm + m] = theta_[n];
322  }
323  }
324  size_t nsp = m_lattice[n]->nSpecies();
325  lkstart_[n] = loc;
326  for (size_t k = 0; k < nsp; k++) {
327  m_x[loc] =m_lattice[n]->moleFraction(k) / (double) m_lattice.size();
328  loc++;
329  }
330  lkstart_[n+1] = loc;
331  }
332 
333  setMoleFractions(m_x.data());
335 }
336 
337 bool LatticeSolidPhase::addSpecies(shared_ptr<Species> spec)
338 {
339  bool added = ThermoPhase::addSpecies(spec);
340  if (added) {
341  m_x.push_back(0.0);
342  tmpV_.push_back(0.0);
343  }
344  return added;
345 }
346 
347 void LatticeSolidPhase::addLattice(shared_ptr<ThermoPhase> lattice)
348 {
349  m_lattice.push_back(lattice);
350  if (theta_.size() == 0) {
351  theta_.push_back(1.0);
352  } else {
353  theta_.push_back(0.0);
354  }
355 }
356 
358 {
359  for (size_t i = 0; i < m_lattice.size(); i++) {
360  theta_[i] = getValue(comp, m_lattice[i]->name(), 0.0);
361  }
362 }
363 
365 {
366  doublereal tnow = temperature();
367  if (m_tlast != tnow) {
368  getMoleFractions(m_x.data());
369  size_t strt = 0;
370  for (size_t n = 0; n < m_lattice.size(); n++) {
371  m_lattice[n]->setTemperature(tnow);
372  m_lattice[n]->setMoleFractions(&m_x[strt]);
373  m_lattice[n]->setPressure(m_press);
374  strt += m_lattice[n]->nSpecies();
375  }
376  m_tlast = tnow;
377  }
378 }
379 
380 void LatticeSolidPhase::setLatticeMoleFractionsByName(int nn, const std::string& x)
381 {
382  m_lattice[nn]->setMoleFractionsByName(x);
383  size_t loc = 0;
384  for (size_t n = 0; n < m_lattice.size(); n++) {
385  size_t nsp = m_lattice[n]->nSpecies();
386  double ndens = m_lattice[n]->molarDensity();
387  for (size_t k = 0; k < nsp; k++) {
388  m_x[loc] = ndens * m_lattice[n]->moleFraction(k);
389  loc++;
390  }
391  }
392  setMoleFractions(m_x.data());
393 }
394 
396 {
397  eosdata._require("model","LatticeSolid");
398  XML_Node& la = eosdata.child("LatticeArray");
399  std::vector<XML_Node*> lattices = la.getChildren("phase");
400  for (auto lattice : lattices) {
401  addLattice(shared_ptr<ThermoPhase>(newPhase(*lattice)));
402  }
403  setLatticeStoichiometry(parseCompString(eosdata.child("LatticeStoichiometry").value()));
404 }
405 
406 void LatticeSolidPhase::modifyOneHf298SS(const size_t k, const doublereal Hf298New)
407 {
408  for (size_t n = 0; n < m_lattice.size(); n++) {
409  if (lkstart_[n+1] < k) {
410  size_t kk = k-lkstart_[n];
411  MultiSpeciesThermo& l_spthermo = m_lattice[n]->speciesThermo();
412  l_spthermo.modifyOneHf298(kk, Hf298New);
413  }
414  }
415  invalidateCache();
416  _updateThermo();
417 }
418 
419 void LatticeSolidPhase::resetHf298(const size_t k)
420 {
421  if (k != npos) {
422  for (size_t n = 0; n < m_lattice.size(); n++) {
423  if (lkstart_[n+1] < k) {
424  size_t kk = k-lkstart_[n];
425  m_lattice[n]->speciesThermo().resetHf298(kk);
426  }
427  }
428  } else {
429  for (size_t n = 0; n < m_lattice.size(); n++) {
430  m_lattice[n]->speciesThermo().resetHf298(npos);
431  }
432  }
433  invalidateCache();
434  _updateThermo();
435 }
436 
437 } // End namespace Cantera
Header for a general species thermodynamic property manager for a phase (see MultiSpeciesThermo).
std::map< std::string, doublereal > compositionMap
Map connecting a string name with a double.
Definition: ct_defs.h:149
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:88
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.
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.
Headers for the factory class that can create known ThermoPhase objects (see Thermodynamic Properties...
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
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.
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:1643
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:748
virtual doublereal standardConcentration(size_t k=0) const
Return the standard concentration for the kth species.
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).
virtual void resetHf298(const size_t k=npos)
Restore the original heat of formation of one or more species.
virtual void getChemPotentials(doublereal *mu) const
Get the species chemical potentials. Units: J/kmol.
vector_fp tmpV_
Temporary vector.
virtual void getActivityCoefficients(doublereal *ac) const
Get the array of non-dimensional molar-based activity coefficients at the current solution temperatur...
const U & getValue(const std::map< T, U > &m, const T &key, const U &default_val)
Const accessor for a value in a std::map.
Definition: utilities.h:504
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:65
std::string value() const
Return the value of an XML node as a string.
Definition: xml.cpp:449
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:251
void addLattice(shared_ptr< ThermoPhase > lattice)
Add a lattice to this phase.
void setLatticeStoichiometry(const compositionMap &comp)
Set the lattice stoichiometric coefficients, .
void getMoleFractions(doublereal *const x) const
Get the species mole fraction vector.
Definition: Phase.cpp:466
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
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.
Definition: stringUtils.cpp:60
vector_fp m_x
Vector of mole fractions.
Header for factory functions to build instances of classes that manage the standard-state thermodynam...
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:629
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.
virtual bool addSpecies(shared_ptr< Species > spec)
std::string name() const
Return the name of the phase.
Definition: Phase.cpp:78
virtual doublereal maxTemp(size_t k=npos) const
Maximum temperature for which the thermodynamic data for the species are valid.
std::vector< shared_ptr< ThermoPhase > > m_lattice
Vector of sublattic ThermoPhase objects.
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:797
#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:788
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: AnyMap.cpp:8
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...
virtual doublereal enthalpy_mole() const
Return the Molar Enthalpy. Units: J/kmol.
virtual doublereal gibbs_mole() const
Return the Molar Gibbs energy. Units: J/kmol.
virtual void setDensity(const doublereal density_)
Set the internally stored density (kg/m^3) of the phase.
Definition: Phase.h:622