Cantera  2.5.1
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 https://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  return Units(1.0);
122 }
123 
125 {
126  _updateThermo();
127  size_t strt = 0;
128  for (size_t n = 0; n < m_lattice.size(); n++) {
129  m_lattice[n]->getMoleFractions(c+strt);
130  strt += m_lattice[n]->nSpecies();
131  }
132 }
133 
135 {
136  for (size_t k = 0; k < m_kk; k++) {
137  ac[k] = 1.0;
138  }
139 }
140 
142 {
143  return 1.0;
144 }
145 
146 doublereal LatticeSolidPhase::logStandardConc(size_t k) const
147 {
148  return 0.0;
149 }
150 
152 {
153  m_press = p;
154  for (size_t n = 0; n < m_lattice.size(); n++) {
155  m_lattice[n]->setPressure(m_press);
156  }
157  calcDensity();
158 }
159 
161 {
162  double sum = 0.0;
163  for (size_t n = 0; n < m_lattice.size(); n++) {
164  sum += theta_[n] * m_lattice[n]->density();
165  }
167  return sum;
168 }
169 
170 void LatticeSolidPhase::setMoleFractions(const doublereal* const x)
171 {
172  size_t strt = 0;
173  for (size_t n = 0; n < m_lattice.size(); n++) {
174  size_t nsp = m_lattice[n]->nSpecies();
175  m_lattice[n]->setMoleFractions(x + strt);
176  strt += nsp;
177  }
178  for (size_t k = 0; k < strt; k++) {
179  m_x[k] = x[k] / m_lattice.size();
180  }
182  calcDensity();
183 }
184 
185 void LatticeSolidPhase::getMoleFractions(doublereal* const x) const
186 {
187  size_t strt = 0;
188  // the ifdef block should be the way we calculate this.!!!!!
190  for (size_t n = 0; n < m_lattice.size(); n++) {
191  size_t nsp = m_lattice[n]->nSpecies();
192  double sum = 0.0;
193  for (size_t k = 0; k < nsp; k++) {
194  sum += (x + strt)[k];
195  }
196  for (size_t k = 0; k < nsp; k++) {
197  (x + strt)[k] /= sum;
198  }
199 
200  // At this point we can check against the mole fraction vector of the
201  // underlying LatticePhase objects and get the same answer.
202  m_lattice[n]->getMoleFractions(&m_x[strt]);
203  for (size_t k = 0; k < nsp; k++) {
204  if (fabs((x + strt)[k] - m_x[strt+k]) > 1.0E-14) {
205  throw CanteraError("LatticeSolidPhase::getMoleFractions",
206  "internal error");
207  }
208  }
209  strt += nsp;
210  }
211 }
212 
213 void LatticeSolidPhase::getChemPotentials(doublereal* mu) const
214 {
215  _updateThermo();
216  size_t strt = 0;
217  for (size_t n = 0; n < m_lattice.size(); n++) {
218  size_t nlsp = m_lattice[n]->nSpecies();
219  m_lattice[n]->getChemPotentials(mu+strt);
220  strt += nlsp;
221  }
222 }
223 
225 {
226  _updateThermo();
227  size_t strt = 0;
228  for (size_t n = 0; n < m_lattice.size(); n++) {
229  size_t nlsp = m_lattice[n]->nSpecies();
230  m_lattice[n]->getPartialMolarEnthalpies(hbar + strt);
231  strt += nlsp;
232  }
233 }
234 
236 {
237  _updateThermo();
238  size_t strt = 0;
239  for (size_t n = 0; n < m_lattice.size(); n++) {
240  size_t nlsp = m_lattice[n]->nSpecies();
241  m_lattice[n]->getPartialMolarEntropies(sbar + strt);
242  strt += nlsp;
243  }
244 }
245 
246 void LatticeSolidPhase::getPartialMolarCp(doublereal* cpbar) const
247 {
248  _updateThermo();
249  size_t strt = 0;
250  for (size_t n = 0; n < m_lattice.size(); n++) {
251  size_t nlsp = m_lattice[n]->nSpecies();
252  m_lattice[n]->getPartialMolarCp(cpbar + strt);
253  strt += nlsp;
254  }
255 }
256 
257 void LatticeSolidPhase::getPartialMolarVolumes(doublereal* vbar) const
258 {
259  _updateThermo();
260  size_t strt = 0;
261  for (size_t n = 0; n < m_lattice.size(); n++) {
262  size_t nlsp = m_lattice[n]->nSpecies();
263  m_lattice[n]->getPartialMolarVolumes(vbar + strt);
264  strt += nlsp;
265  }
266 }
267 
269 {
270  _updateThermo();
271  size_t strt = 0;
272  for (size_t n = 0; n < m_lattice.size(); n++) {
273  m_lattice[n]->getStandardChemPotentials(mu0+strt);
274  strt += m_lattice[n]->nSpecies();
275  }
276 }
277 
278 void LatticeSolidPhase::getGibbs_RT_ref(doublereal* grt) const
279 {
280  _updateThermo();
281  for (size_t n = 0; n < m_lattice.size(); n++) {
282  m_lattice[n]->getGibbs_RT_ref(grt + lkstart_[n]);
283  }
284 }
285 
286 void LatticeSolidPhase::getGibbs_ref(doublereal* g) const
287 {
288  getGibbs_RT_ref(g);
289  for (size_t k = 0; k < m_kk; k++) {
290  g[k] *= RT();
291  }
292 }
293 
295  const AnyMap& rootNode)
296 {
297  ThermoPhase::setParameters(phaseNode, rootNode);
298  m_rootNode = rootNode;
299 }
300 
302 {
303  if (m_input.hasKey("composition")) {
304  compositionMap composition = m_input["composition"].asMap<double>();
305  for (auto& item : composition) {
306  AnyMap& node = m_rootNode["phases"].getMapWhere("name", item.first);
308  }
309  setLatticeStoichiometry(composition);
310  }
311 
312  setMoleFractions(m_x.data());
314 }
315 
316 bool LatticeSolidPhase::addSpecies(shared_ptr<Species> spec)
317 {
318  // Species are added from component phases in addLattice()
319  return false;
320 }
321 
322 void LatticeSolidPhase::addLattice(shared_ptr<ThermoPhase> lattice)
323 {
324  m_lattice.push_back(lattice);
325  if (lkstart_.empty()) {
326  lkstart_.push_back(0);
327  }
328  lkstart_.push_back(lkstart_.back() + lattice->nSpecies());
329 
330  if (theta_.size() == 0) {
331  theta_.push_back(1.0);
332  } else {
333  theta_.push_back(0.0);
334  }
335 
336  for (size_t k = 0; k < lattice->nSpecies(); k++) {
337  ThermoPhase::addSpecies(lattice->species(k));
338  vector_fp constArr(lattice->nElements());
339  const vector_fp& aws = lattice->atomicWeights();
340  for (size_t es = 0; es < lattice->nElements(); es++) {
341  addElement(lattice->elementName(es), aws[es], lattice->atomicNumber(es),
342  lattice->entropyElement298(es), lattice->elementType(es));
343  }
344  m_x.push_back(lattice->moleFraction(k));
345  tmpV_.push_back(0.0);
346  }
347 }
348 
350 {
351  for (size_t i = 0; i < m_lattice.size(); i++) {
352  theta_[i] = getValue(comp, m_lattice[i]->name(), 0.0);
353  }
354  // Add in the lattice stoichiometry constraint
355  for (size_t i = 1; i < m_lattice.size(); i++) {
356  string econ = fmt::format("LC_{}_{}", i, name());
357  size_t m = addElement(econ, 0.0, 0, 0.0, CT_ELEM_TYPE_LATTICERATIO);
358  size_t mm = nElements();
359  for (size_t k = 0; k < m_lattice[0]->nSpecies(); k++) {
360  m_speciesComp[k * mm + m] = -theta_[0];
361  }
362  for (size_t k = 0; k < m_lattice[i]->nSpecies(); k++) {
363  size_t ks = lkstart_[i] + k;
364  m_speciesComp[ks * mm + m] = theta_[i];
365  }
366  }
367 }
368 
370 {
371  doublereal tnow = temperature();
372  if (m_tlast != tnow) {
373  getMoleFractions(m_x.data());
374  size_t strt = 0;
375  for (size_t n = 0; n < m_lattice.size(); n++) {
376  m_lattice[n]->setTemperature(tnow);
377  m_lattice[n]->setMoleFractions(&m_x[strt]);
378  m_lattice[n]->setPressure(m_press);
379  strt += m_lattice[n]->nSpecies();
380  }
381  m_tlast = tnow;
382  }
383 }
384 
385 void LatticeSolidPhase::setLatticeMoleFractionsByName(int nn, const std::string& x)
386 {
387  m_lattice[nn]->setMoleFractionsByName(x);
388  size_t loc = 0;
389  for (size_t n = 0; n < m_lattice.size(); n++) {
390  size_t nsp = m_lattice[n]->nSpecies();
391  double ndens = m_lattice[n]->molarDensity();
392  for (size_t k = 0; k < nsp; k++) {
393  m_x[loc] = ndens * m_lattice[n]->moleFraction(k);
394  loc++;
395  }
396  }
397  setMoleFractions(m_x.data());
398 }
399 
401 {
402  eosdata._require("model","LatticeSolid");
403  XML_Node& la = eosdata.child("LatticeArray");
404  std::vector<XML_Node*> lattices = la.getChildren("phase");
405  for (auto lattice : lattices) {
406  addLattice(shared_ptr<ThermoPhase>(newPhase(*lattice)));
407  }
408  setLatticeStoichiometry(parseCompString(eosdata.child("LatticeStoichiometry").value()));
409 }
410 
411 void LatticeSolidPhase::modifyOneHf298SS(const size_t k, const doublereal Hf298New)
412 {
413  for (size_t n = 0; n < m_lattice.size(); n++) {
414  if (lkstart_[n+1] < k) {
415  size_t kk = k-lkstart_[n];
416  MultiSpeciesThermo& l_spthermo = m_lattice[n]->speciesThermo();
417  l_spthermo.modifyOneHf298(kk, Hf298New);
418  }
419  }
420  invalidateCache();
421  _updateThermo();
422 }
423 
424 void LatticeSolidPhase::resetHf298(const size_t k)
425 {
426  if (k != npos) {
427  for (size_t n = 0; n < m_lattice.size(); n++) {
428  if (lkstart_[n+1] < k) {
429  size_t kk = k-lkstart_[n];
430  m_lattice[n]->speciesThermo().resetHf298(kk);
431  }
432  }
433  } else {
434  for (size_t n = 0; n < m_lattice.size(); n++) {
435  m_lattice[n]->speciesThermo().resetHf298(npos);
436  }
437  }
438  invalidateCache();
439  _updateThermo();
440 }
441 
442 } // End namespace Cantera
#define CT_ELEM_TYPE_LATTICERATIO
Constraint associated with maintaining a fixed lattice stoichiometry in a solid.
Definition: Elements.h:56
Header for a simple thermodynamics model of a bulk solid phase derived from ThermoPhase,...
Header for a general species thermodynamic property manager for a phase (see MultiSpeciesThermo).
Header for factory functions to build instances of classes that manage the standard-state thermodynam...
Headers for the factory class that can create known ThermoPhase objects (see Thermodynamic Properties...
A map of string keys to values whose type can vary at runtime.
Definition: AnyMap.h:360
bool hasKey(const std::string &key) const
Returns true if the map contains an item named key.
Definition: AnyMap.cpp:984
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:61
virtual void getMoleFractions(doublereal *const x) const
Get the species mole fraction vector.
virtual doublereal minTemp(size_t k=npos) const
Minimum temperature for which the thermodynamic data for the species or phase are valid.
doublereal m_press
Current value of the pressure.
AnyMap m_rootNode
Root node of the AnyMap which contains this phase definition.
virtual bool addSpecies(shared_ptr< Species > spec)
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 setParameters(const AnyMap &phaseNode, const AnyMap &rootNode=AnyMap())
Set equation of state parameters from an AnyMap phase description.
virtual void getActivityCoefficients(doublereal *ac) const
Get the array of non-dimensional molar-based activity coefficients at the current solution temperatur...
vector_fp m_x
Vector of mole fractions.
std::vector< shared_ptr< ThermoPhase > > m_lattice
Vector of sublattic ThermoPhase objects.
virtual doublereal cp_mole() const
Return the constant pressure heat capacity. Units: J/kmol/K.
virtual void getPartialMolarEnthalpies(doublereal *hbar) const
Returns an array of partial molar enthalpies for the species in the mixture.
virtual void getPartialMolarEntropies(doublereal *sbar) const
Returns an array of partial molar entropies of the species in the solution.
virtual doublereal enthalpy_mole() const
Return the Molar Enthalpy. Units: J/kmol.
virtual doublereal logStandardConc(size_t k=0) const
Natural logarithm of the standard concentration of the kth species.
virtual void getPartialMolarVolumes(doublereal *vbar) const
returns an array of partial molar volumes of the species in the solution.
doublereal calcDensity()
Calculate the density of the solid mixture.
virtual void getActivityConcentrations(doublereal *c) const
This method returns an array of generalized concentrations.
void setLatticeMoleFractionsByName(int n, const std::string &x)
Set the Lattice mole fractions using a string.
virtual void getPartialMolarCp(doublereal *cpbar) const
Returns an array of partial molar Heat Capacities at constant pressure of the species in the solution...
virtual void getStandardChemPotentials(doublereal *mu0) const
Get the array of standard state chemical potentials at unit activity for the species at their standar...
virtual void setPressure(doublereal p)
Set the pressure at constant temperature. Units: Pa.
virtual doublereal entropy_mole() const
Return the Molar Entropy. Units: J/kmol/K.
virtual void initThermo()
Initialize the ThermoPhase object after all species have been set up.
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....
virtual doublereal refPressure() const
Returns the reference pressure in Pa.
virtual void resetHf298(const size_t k=npos)
Restore the original heat of formation of one or more species.
vector_fp theta_
Lattice stoichiometric coefficients.
virtual doublereal gibbs_mole() const
Return the Molar Gibbs energy. Units: J/kmol.
virtual Units standardConcentrationUnits() const
Returns the units of the "standard concentration" for this phase.
virtual void setParametersFromXML(const XML_Node &eosdata)
Set equation of state parameter values from XML entries.
void setLatticeStoichiometry(const compositionMap &comp)
Set the lattice stoichiometric coefficients, .
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)
void addLattice(shared_ptr< ThermoPhase > lattice)
Add a lattice to this phase.
void _updateThermo() const
Update the reference thermodynamic functions.
virtual void getChemPotentials(doublereal *mu) const
Get the species chemical potentials. Units: J/kmol.
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...
vector_fp tmpV_
Temporary vector.
virtual doublereal maxTemp(size_t k=npos) const
Maximum temperature for which the thermodynamic data for the species are valid.
virtual doublereal intEnergy_mole() const
Return the Molar Internal Energy. Units: J/kmol.
virtual doublereal standardConcentration(size_t k=0) const
Return the standard concentration for the kth species.
A species thermodynamic property manager for a phase.
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 ...
void assignDensity(const double density_)
Set the internally stored constant density (kg/m^3) of the phase.
Definition: Phase.cpp:727
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:765
virtual void setMoleFractions(const double *const x)
Set the mole fractions to the specified values.
Definition: Phase.cpp:368
std::string name() const
Return the name of the phase.
Definition: Phase.cpp:84
size_t m_kk
Number of species in the phase.
Definition: Phase.h:942
vector_fp m_speciesComp
Atomic composition of the species.
Definition: Phase.h:951
void getMoleFractions(double *const x) const
Get the species mole fraction vector.
Definition: Phase.cpp:572
doublereal temperature() const
Temperature (K).
Definition: Phase.h:667
size_t nElements() const
Number of elements.
Definition: Phase.cpp:95
virtual bool addSpecies(shared_ptr< Species > spec)
doublereal RT() const
Return the Gas Constant multiplied by the current temperature.
Definition: ThermoPhase.h:776
doublereal m_tlast
last value of the temperature processed by reference state
Definition: ThermoPhase.h:1904
virtual void initThermo()
Initialize the ThermoPhase object after all species have been set up.
virtual void setParameters(int n, doublereal *const c)
Set the equation of state parameters.
Definition: ThermoPhase.h:1691
AnyMap m_input
Data supplied via setParameters.
Definition: ThermoPhase.h:1874
virtual void invalidateCache()
Invalidate any cached values which are normally updated only when a change in state is detected.
A representation of the units associated with a dimensional quantity.
Definition: Units.h:30
Class XML_Node is a tree-based representation of the contents of an XML file.
Definition: xml.h:104
void _require(const std::string &a, const std::string &v) const
Require that the current XML node has an attribute named by the first argument, a,...
Definition: xml.cpp:576
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:711
std::string value() const
Return the value of an XML node as a string.
Definition: xml.cpp:441
XML_Node & child(const size_t n) const
Return a changeable reference to the n'th child of the current node.
Definition: xml.cpp:546
CTML ("Cantera Markup Language") is the variant of XML that Cantera uses to store data.
ThermoPhase * newPhase(XML_Node &xmlphase)
Create a new ThermoPhase object and initializes it according to the XML tree.
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:188
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:180
std::map< std::string, double > compositionMap
Map connecting a string name with a double.
Definition: ct_defs.h:172
Namespace for the Cantera kernel.
Definition: AnyMap.cpp:264
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:528
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
Contains declarations for string manipulation functions within Cantera.
Various templated functions that carry out common vector operations (see Templated Utility Functions)...