Cantera 2.6.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 https://cantera.org/license.txt for license and copyright information.
11
16#include "cantera/base/ctml.h"
19
20#include <boost/algorithm/string.hpp>
21
22using namespace std;
23namespace ba = boost::algorithm;
24
25namespace Cantera
26{
28 m_press(-1.0),
29 m_molar_density(0.0)
30{
31}
32
33doublereal LatticeSolidPhase::minTemp(size_t k) const
34{
35 if (k != npos) {
36 for (size_t n = 0; n < m_lattice.size(); n++) {
37 if (lkstart_[n+1] < k) {
38 return m_lattice[n]->minTemp(k-lkstart_[n]);
39 }
40 }
41 }
42 doublereal mm = 1.0E300;
43 for (size_t n = 0; n < m_lattice.size(); n++) {
44 double ml = m_lattice[n]->minTemp();
45 mm = std::min(mm, ml);
46 }
47 return mm;
48}
49
50doublereal LatticeSolidPhase::maxTemp(size_t k) const
51{
52 if (k != npos) {
53 for (size_t n = 0; n < m_lattice.size(); n++) {
54 if (lkstart_[n+1] < k) {
55 return (m_lattice[n])->maxTemp(k - lkstart_[n]);
56 }
57 }
58 }
59 doublereal mm = -1.0E300;
60 for (size_t n = 0; n < m_lattice.size(); n++) {
61 double ml = m_lattice[n]->maxTemp();
62 mm = std::max(mm, ml);
63 }
64 return mm;
65}
66
68{
69 return m_lattice[0]->refPressure();
70}
71
73{
75 doublereal sum = 0.0;
76 for (size_t n = 0; n < m_lattice.size(); n++) {
77 sum += theta_[n] * m_lattice[n]->enthalpy_mole();
78 }
79 return sum;
80}
81
83{
85 doublereal sum = 0.0;
86 for (size_t n = 0; n < m_lattice.size(); n++) {
87 sum += theta_[n] * m_lattice[n]->intEnergy_mole();
88 }
89 return sum;
90}
91
93{
95 doublereal sum = 0.0;
96 for (size_t n = 0; n < m_lattice.size(); n++) {
97 sum += theta_[n] * m_lattice[n]->entropy_mole();
98 }
99 return sum;
100}
101
103{
105 doublereal sum = 0.0;
106 for (size_t n = 0; n < m_lattice.size(); n++) {
107 sum += theta_[n] * m_lattice[n]->gibbs_mole();
108 }
109 return sum;
110}
111
113{
115 doublereal sum = 0.0;
116 for (size_t n = 0; n < m_lattice.size(); n++) {
117 sum += theta_[n] * m_lattice[n]->cp_mole();
118 }
119 return sum;
120}
121
123{
124 return Units(1.0);
125}
126
128{
130 size_t strt = 0;
131 for (size_t n = 0; n < m_lattice.size(); n++) {
132 m_lattice[n]->getMoleFractions(c+strt);
133 strt += m_lattice[n]->nSpecies();
134 }
135}
136
138{
139 for (size_t k = 0; k < m_kk; k++) {
140 ac[k] = 1.0;
141 }
142}
143
145{
146 return 1.0;
147}
148
149doublereal LatticeSolidPhase::logStandardConc(size_t k) const
150{
151 return 0.0;
152}
153
155{
156 m_press = p;
157 for (size_t n = 0; n < m_lattice.size(); n++) {
158 m_lattice[n]->setPressure(m_press);
159 }
160 calcDensity();
161}
162
164{
165 double sum = 0.0;
166 for (size_t n = 0; n < m_lattice.size(); n++) {
167 sum += theta_[n] * m_lattice[n]->density();
168 }
170 return sum;
171}
172
173void LatticeSolidPhase::setMoleFractions(const doublereal* const x)
174{
175 size_t strt = 0;
176 for (size_t n = 0; n < m_lattice.size(); n++) {
177 size_t nsp = m_lattice[n]->nSpecies();
178 m_lattice[n]->setMoleFractions(x + strt);
179 strt += nsp;
180 }
181 for (size_t k = 0; k < strt; k++) {
182 m_x[k] = x[k] / m_lattice.size();
183 }
185 calcDensity();
186}
187
188void LatticeSolidPhase::getMoleFractions(doublereal* const x) const
189{
190 size_t strt = 0;
191 // the ifdef block should be the way we calculate this.!!!!!
193 for (size_t n = 0; n < m_lattice.size(); n++) {
194 size_t nsp = m_lattice[n]->nSpecies();
195 double sum = 0.0;
196 for (size_t k = 0; k < nsp; k++) {
197 sum += (x + strt)[k];
198 }
199 for (size_t k = 0; k < nsp; k++) {
200 (x + strt)[k] /= sum;
201 }
202
203 // At this point we can check against the mole fraction vector of the
204 // underlying LatticePhase objects and get the same answer.
205 m_lattice[n]->getMoleFractions(&m_x[strt]);
206 for (size_t k = 0; k < nsp; k++) {
207 if (fabs((x + strt)[k] - m_x[strt+k]) > 1.0E-14) {
208 throw CanteraError("LatticeSolidPhase::getMoleFractions",
209 "internal error");
210 }
211 }
212 strt += nsp;
213 }
214}
215
216void LatticeSolidPhase::getChemPotentials(doublereal* mu) const
217{
219 size_t strt = 0;
220 for (size_t n = 0; n < m_lattice.size(); n++) {
221 size_t nlsp = m_lattice[n]->nSpecies();
222 m_lattice[n]->getChemPotentials(mu+strt);
223 strt += nlsp;
224 }
225}
226
228{
230 size_t strt = 0;
231 for (size_t n = 0; n < m_lattice.size(); n++) {
232 size_t nlsp = m_lattice[n]->nSpecies();
233 m_lattice[n]->getPartialMolarEnthalpies(hbar + strt);
234 strt += nlsp;
235 }
236}
237
239{
241 size_t strt = 0;
242 for (size_t n = 0; n < m_lattice.size(); n++) {
243 size_t nlsp = m_lattice[n]->nSpecies();
244 m_lattice[n]->getPartialMolarEntropies(sbar + strt);
245 strt += nlsp;
246 }
247}
248
249void LatticeSolidPhase::getPartialMolarCp(doublereal* cpbar) const
250{
252 size_t strt = 0;
253 for (size_t n = 0; n < m_lattice.size(); n++) {
254 size_t nlsp = m_lattice[n]->nSpecies();
255 m_lattice[n]->getPartialMolarCp(cpbar + strt);
256 strt += nlsp;
257 }
258}
259
261{
263 size_t strt = 0;
264 for (size_t n = 0; n < m_lattice.size(); n++) {
265 size_t nlsp = m_lattice[n]->nSpecies();
266 m_lattice[n]->getPartialMolarVolumes(vbar + strt);
267 strt += nlsp;
268 }
269}
270
272{
274 size_t strt = 0;
275 for (size_t n = 0; n < m_lattice.size(); n++) {
276 m_lattice[n]->getStandardChemPotentials(mu0+strt);
277 strt += m_lattice[n]->nSpecies();
278 }
279}
280
281void LatticeSolidPhase::getGibbs_RT_ref(doublereal* grt) const
282{
284 for (size_t n = 0; n < m_lattice.size(); n++) {
285 m_lattice[n]->getGibbs_RT_ref(grt + lkstart_[n]);
286 }
287}
288
289void LatticeSolidPhase::getGibbs_ref(doublereal* g) const
290{
292 for (size_t k = 0; k < m_kk; k++) {
293 g[k] *= RT();
294 }
295}
296
298 const AnyMap& rootNode)
299{
300 ThermoPhase::setParameters(phaseNode, rootNode);
301 m_rootNode = rootNode;
302}
303
305{
306 if (m_input.hasKey("composition")) {
307 compositionMap composition = m_input["composition"].asMap<double>();
308 for (auto& item : composition) {
309 AnyMap& node = m_rootNode["phases"].getMapWhere("name", item.first);
311 }
312 setLatticeStoichiometry(composition);
313 }
314
315 setMoleFractions(m_x.data());
317}
318
320{
322 AnyMap composition;
323 for (size_t i = 0; i < m_lattice.size(); i++) {
324 composition[m_lattice[i]->name()] = theta_[i];
325 }
326 phaseNode["composition"] = std::move(composition);
327
328 // Remove fields not used in this model
329 phaseNode.erase("species");
330 vector<std::string> elements;
331 for (auto& el : phaseNode["elements"].asVector<std::string>()) {
332 if (!ba::starts_with(el, "LC_")) {
333 elements.push_back(el);
334 }
335 }
336 phaseNode["elements"] = elements;
337}
338
339void LatticeSolidPhase::getSpeciesParameters(const std::string& name,
340 AnyMap& speciesNode) const
341{
342 // Use child lattice phases to determine species parameters so that these
343 // are set consistently
344 for (const auto& phase : m_lattice) {
345 if (phase->speciesIndex(name) != npos) {
346 phase->getSpeciesParameters(name, speciesNode);
347 break;
348 }
349 }
350}
351
352bool LatticeSolidPhase::addSpecies(shared_ptr<Species> spec)
353{
354 // Species are added from component phases in addLattice()
355 return false;
356}
357
358void LatticeSolidPhase::addLattice(shared_ptr<ThermoPhase> lattice)
359{
360 m_lattice.push_back(lattice);
361 if (lkstart_.empty()) {
362 lkstart_.push_back(0);
363 }
364 lkstart_.push_back(lkstart_.back() + lattice->nSpecies());
365
366 if (theta_.size() == 0) {
367 theta_.push_back(1.0);
368 } else {
369 theta_.push_back(0.0);
370 }
371
372 for (size_t k = 0; k < lattice->nSpecies(); k++) {
373 ThermoPhase::addSpecies(lattice->species(k));
374 vector_fp constArr(lattice->nElements());
375 const vector_fp& aws = lattice->atomicWeights();
376 for (size_t es = 0; es < lattice->nElements(); es++) {
377 addElement(lattice->elementName(es), aws[es], lattice->atomicNumber(es),
378 lattice->entropyElement298(es), lattice->elementType(es));
379 }
380 m_x.push_back(lattice->moleFraction(k));
381 tmpV_.push_back(0.0);
382 }
383}
384
386{
387 for (size_t i = 0; i < m_lattice.size(); i++) {
388 theta_[i] = getValue(comp, m_lattice[i]->name(), 0.0);
389 }
390 // Add in the lattice stoichiometry constraint
391 for (size_t i = 1; i < m_lattice.size(); i++) {
392 string econ = fmt::format("LC_{}_{}", i, name());
393 size_t m = addElement(econ, 0.0, 0, 0.0, CT_ELEM_TYPE_LATTICERATIO);
394 size_t mm = nElements();
395 for (size_t k = 0; k < m_lattice[0]->nSpecies(); k++) {
396 m_speciesComp[k * mm + m] = -theta_[0];
397 }
398 for (size_t k = 0; k < m_lattice[i]->nSpecies(); k++) {
399 size_t ks = lkstart_[i] + k;
400 m_speciesComp[ks * mm + m] = theta_[i];
401 }
402 }
403}
404
406{
407 doublereal tnow = temperature();
408 if (m_tlast != tnow) {
409 getMoleFractions(m_x.data());
410 size_t strt = 0;
411 for (size_t n = 0; n < m_lattice.size(); n++) {
412 m_lattice[n]->setTemperature(tnow);
413 m_lattice[n]->setMoleFractions(&m_x[strt]);
414 m_lattice[n]->setPressure(m_press);
415 strt += m_lattice[n]->nSpecies();
416 }
417 m_tlast = tnow;
418 }
419}
420
421void LatticeSolidPhase::setLatticeMoleFractionsByName(int nn, const std::string& x)
422{
423 m_lattice[nn]->setMoleFractionsByName(x);
424 size_t loc = 0;
425 for (size_t n = 0; n < m_lattice.size(); n++) {
426 size_t nsp = m_lattice[n]->nSpecies();
427 double ndens = m_lattice[n]->molarDensity();
428 for (size_t k = 0; k < nsp; k++) {
429 m_x[loc] = ndens * m_lattice[n]->moleFraction(k);
430 loc++;
431 }
432 }
433 setMoleFractions(m_x.data());
434}
435
437{
438 eosdata._require("model","LatticeSolid");
439 XML_Node& la = eosdata.child("LatticeArray");
440 std::vector<XML_Node*> lattices = la.getChildren("phase");
441 for (auto lattice : lattices) {
442 addLattice(shared_ptr<ThermoPhase>(newPhase(*lattice)));
443 }
444 setLatticeStoichiometry(parseCompString(eosdata.child("LatticeStoichiometry").value()));
445}
446
447void LatticeSolidPhase::modifyOneHf298SS(const size_t k, const doublereal Hf298New)
448{
449 for (size_t n = 0; n < m_lattice.size(); n++) {
450 if (lkstart_[n+1] < k) {
451 size_t kk = k-lkstart_[n];
452 MultiSpeciesThermo& l_spthermo = m_lattice[n]->speciesThermo();
453 l_spthermo.modifyOneHf298(kk, Hf298New);
454 }
455 }
458}
459
461{
462 if (k != npos) {
463 for (size_t n = 0; n < m_lattice.size(); n++) {
464 if (lkstart_[n+1] < k) {
465 size_t kk = k-lkstart_[n];
466 m_lattice[n]->speciesThermo().resetHf298(kk);
467 }
468 }
469 } else {
470 for (size_t n = 0; n < m_lattice.size(); n++) {
471 m_lattice[n]->speciesThermo().resetHf298(npos);
472 }
473 }
476}
477
478} // 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:399
void erase(const std::string &key)
Erase the value held by key.
Definition: AnyMap.cpp:1411
bool hasKey(const std::string &key) const
Returns true if the map contains an item named key.
Definition: AnyMap.cpp:1406
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)
LatticeSolidPhase()
Base empty constructor.
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 getParameters(AnyMap &phaseNode) const
Store the parameters of a ThermoPhase object such that an identical one could be reconstructed using ...
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.
virtual void getSpeciesParameters(const std::string &name, AnyMap &speciesNode) const
Get phase-specific parameters of a Species object such that an identical one could be reconstructed a...
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:698
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:736
virtual void setMoleFractions(const double *const x)
Set the mole fractions to the specified values.
Definition: Phase.cpp:339
std::string name() const
Return the name of the phase.
Definition: Phase.cpp:70
size_t m_kk
Number of species in the phase.
Definition: Phase.h:943
vector_fp m_speciesComp
Atomic composition of the species.
Definition: Phase.h:952
void getMoleFractions(double *const x) const
Get the species mole fraction vector.
Definition: Phase.cpp:543
doublereal temperature() const
Temperature (K).
Definition: Phase.h:654
size_t nElements() const
Number of elements.
Definition: Phase.cpp:81
virtual bool addSpecies(shared_ptr< Species > spec)
doublereal RT() const
Return the Gas Constant multiplied by the current temperature.
Definition: ThermoPhase.h:782
doublereal m_tlast
last value of the temperature processed by reference state
Definition: ThermoPhase.h:1928
virtual void initThermo()
Initialize the ThermoPhase object after all species have been set up.
AnyMap m_input
Data supplied via setParameters.
Definition: ThermoPhase.h:1898
virtual void setParameters(int n, doublereal *const c)
Set the equation of state parameters.
virtual void invalidateCache()
Invalidate any cached values which are normally updated only when a change in state is detected.
virtual void getParameters(int &n, doublereal *const c) const
Get the equation of state parameters in a vector.
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:103
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:577
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:712
std::string value() const
Return the value of an XML node as a string.
Definition: xml.cpp:442
XML_Node & child(const size_t n) const
Return a changeable reference to the n'th child of the current node.
Definition: xml.cpp:547
CTML ("Cantera Markup Language") is the variant of XML that Cantera uses to store data.
ThermoPhase * newPhase(XML_Node &phase)
Create a new ThermoPhase object and initializes it according to the XML tree.
Namespace for the Cantera kernel.
Definition: AnyMap.h:29
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:192
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:184
std::map< std::string, double > compositionMap
Map connecting a string name with a double.
Definition: ct_defs.h:176
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:184
compositionMap parseCompString(const std::string &ss, const std::vector< std::string > &names=std::vector< std::string >())
Parse a composition string into a map consisting of individual key:composition pairs.
Definition: stringUtils.cpp:59
Contains declarations for string manipulation functions within Cantera.
Various templated functions that carry out common vector operations (see Templated Utility Functions)...