Cantera  2.0
MetalSHEelectrons.cpp
Go to the documentation of this file.
1 /**
2  * @file MetalSHEelectrons.cpp
3  * Definition file for the %MetalSHEElectrons class, which represents the
4  * electrons in a metal that are consistent with the
5  * SHE electrode (see \ref thermoprops and
6  * class \link Cantera::MetalSHEelectrons MetalSHEelectrons\endlink)
7  */
8 
9 /*
10  * Copyright (2005) Sandia Corporation. Under the terms of
11  * Contract DE-AC04-94AL85000 with Sandia Corporation, the
12  * U.S. Government retains certain rights in this software.
13  *
14  */
15 #include "cantera/base/ct_defs.h"
16 
20 
21 #include <string>
22 using namespace std;
23 using namespace Cantera;
24 
25 namespace Cantera
26 {
27 
28 /*
29  * ---- Constructors -------
30  */
31 //====================================================================================================================
32 /*
33  * Default Constructor for the MetalSHEelectrons class
34  */
35 MetalSHEelectrons::MetalSHEelectrons():
37  xdef_(0)
38 {
39 }
40 //====================================================================================================================
41 // Create and initialize a MetalSHEelectrons ThermoPhase object
42 // from an ASCII input file
43 /*
44  * @param infile name of the input file
45  * @param id name of the phase id in the file.
46  * If this is blank, the first phase in the file is used.
47  */
48 MetalSHEelectrons::MetalSHEelectrons(std::string infile, std::string id) :
50  xdef_(0)
51 {
52  XML_Node* root;
53  if (infile == "MetalSHEelectrons_default.xml") {
55  root = xdef_;
56  } else {
57  root = get_XML_File(infile);
58  }
59  if (id == "-") {
60  id = "";
61  }
62  XML_Node* xphase = get_XML_NameID("phase", std::string("#")+id, root);
63  if (!xphase) {
64  throw CanteraError("MetalSHEelectrons::MetalSHEelectrons",
65  "Couldn't find phase name in file:" + id);
66  }
67  // Check the model name to ensure we have compatibility
68  const XML_Node& th = xphase->child("thermo");
69  std::string model = th["model"];
70  if (model != "MetalSHEelectrons") {
71  throw CanteraError("MetalSHEelectrons::MetalSHEelectrons",
72  "thermo model attribute must be MetalSHEelectrons");
73  }
74  importPhase(*xphase, this);
75 }
76 //====================================================================================================================
77 // Full Constructor.
78 /*
79  * @param phaseRef XML node pointing to a MetalSHEelectrons description
80  * @param id Id of the phase.
81  */
82 MetalSHEelectrons::MetalSHEelectrons(XML_Node& xmlphase, std::string id) :
84  xdef_(0)
85 {
86  if (id != "") {
87  std::string idxml = xmlphase["id"];
88  if (id != idxml) {
89  throw CanteraError("MetalSHEelectrons::MetalSHEelectrons",
90  "id's don't match");
91  }
92  }
93  const XML_Node& th = xmlphase.child("thermo");
94  std::string model = th["model"];
95  if (model != "MetalSHEelectrons") {
96  throw CanteraError("MetalSHEelectrons::MetalSHEelectrons",
97  "thermo model attribute must be MetalSHEelectrons");
98  }
99  importPhase(xmlphase, this);
100 }
101 //====================================================================================================================
102 // Copy constructor
103 /*
104  * @param right Object to be copied
105  */
108 {
109  operator=(right);
110 }
111 //====================================================================================================================
112 /*
113  * Destructor for the routine (virtual)
114  *
115  */
117 {
118  if (xdef_) {
119  delete xdef_;
120  }
121 }
122 //====================================================================================================================
123 // Assignment operator
124 /*
125  * @param right Object to be copied
126  */
129 {
130  if (&right != this) {
132  }
133 
134  if (xdef_) {
135  delete xdef_;
136  }
137  xdef_ = new XML_Node(*right.xdef_);
138 
139  return *this;
140 }
141 //====================================================================================================================
142 // Duplication function
143 /*
144  * This virtual function is used to create a duplicate of the
145  * current phase. It's used to duplicate the phase when given
146  * a ThermoPhase pointer to the phase.
147  *
148  * @return It returns a ThermoPhase pointer.
149  */
151 {
152  MetalSHEelectrons* stp = new MetalSHEelectrons(*this);
153  return (ThermoPhase*) stp;
154 }
155 //====================================================================================================================
156 
157 /*
158  * ---- Utilities -----
159  */
160 
161 /*
162  * Equation of state flag. Returns the value cStoichSubstance,
163  * defined in mix_defs.h.
164  */
166 {
167  return cMetalSHEelectrons;
168 }
169 //====================================================================================================================
170 
171 /*
172  * ---- Molar Thermodynamic properties of the solution ----
173  */
174 
175 /**
176  * ----- Mechanical Equation of State ------
177  */
178 //====================================================================================================================
179 /*
180  * Pressure. Units: Pa.
181  * For an incompressible substance, the density is independent
182  * of pressure. This method simply returns the stored
183  * pressure value.
184  */
185 doublereal MetalSHEelectrons::pressure() const
186 {
187  return m_press;
188 }
189 //====================================================================================================================
190 /*
191  * Set the pressure at constant temperature. Units: Pa.
192  * For an incompressible substance, the density is
193  * independent of pressure. Therefore, this method only
194  * stores the specified pressure value. It does not
195  * modify the density.
196  */
198 {
199  m_press = p;
200 }
201 //====================================================================================================================
202 /*
203  * The isothermal compressibility. Units: 1/Pa.
204  * The isothermal compressibility is defined as
205  * \f[
206  * \kappa_T = -\frac{1}{v}\left(\frac{\partial v}{\partial P}\right)_T
207  * \f]
208  *
209  * It's equal to zero for this model, since the molar volume
210  * doesn't change with pressure or temperature.
211  */
213 {
214  return 1.0/pressure();
215 }
216 //====================================================================================================================
217 /*
218  * The thermal expansion coefficient. Units: 1/K.
219  * The thermal expansion coefficient is defined as
220  *
221  * \f[
222  * \beta = \frac{1}{v}\left(\frac{\partial v}{\partial T}\right)_P
223  * \f]
224  *
225  * It's equal to zero for this model, since the molar volume
226  * doesn't change with pressure or temperature.
227  */
229 {
230  return 1.0/temperature();
231 
232 }
233 //====================================================================================================================
234 /*
235  * ---- Chemical Potentials and Activities ----
236  */
237 //====================================================================================================================
238 /*
239  * This method returns the array of generalized
240  * concentrations. For a stoichiometric substance, there is
241  * only one species, and the generalized concentration is 1.0.
242  */
244 getActivityConcentrations(doublereal* c) const
245 {
246  c[0] = 1.0;
247 }
248 //====================================================================================================================
249 /*
250  * The standard concentration. This is defined as the concentration
251  * by which the generalized concentration is normalized to produce
252  * the activity.
253  */
255 {
256  return 1.0;
257 }
258 //====================================================================================================================
259 /*
260  * Returns the natural logarithm of the standard
261  * concentration of the kth species
262  */
263 doublereal MetalSHEelectrons::logStandardConc(size_t k) const
264 {
265  return 0.0;
266 }
267 //====================================================================================================================
268 /*
269  * Returns the units of the standard and generalized
270  * concentrations Note they have the same units, as their
271  * ratio is defined to be equal to the activity of the kth
272  * species in the solution, which is unitless.
273  *
274  * This routine is used in print out applications where the
275  * units are needed. Usually, MKS units are assumed throughout
276  * the program and in the XML input files.
277  *
278  * uA[0] = kmol units - default = 1
279  * uA[1] = m units - default = -nDim(), the number of spatial
280  * dimensions in the Phase class.
281  * uA[2] = kg units - default = 0;
282  * uA[3] = Pa(pressure) units - default = 0;
283  * uA[4] = Temperature units - default = 0;
284  * uA[5] = time units - default = 0
285  */
287 getUnitsStandardConc(doublereal* uA, int k, int sizeUA) const
288 {
289  for (int i = 0; i < 6; i++) {
290  uA[i] = 0;
291  }
292 }
293 //====================================================================================================================
294 /*
295  * ---- Partial Molar Properties of the Solution ----
296  */
297 
298 //====================================================================================================================
299 
300 /*
301  * ---- Properties of the Standard State of the Species in the Solution
302  * ----
303  */
304 //====================================================================================================================
305 /*
306  * Get the array of chemical potentials at unit activity
307  * \f$ \mu^0_k \f$.
308  *
309  * For a stoichiometric substance, there is no activity term in
310  * the chemical potential expression, and therefore the
311  * standard chemical potential and the chemical potential
312  * are both equal to the molar Gibbs function.
313  */
315 getStandardChemPotentials(doublereal* mu0) const
316 {
317  getGibbs_RT(mu0);
318  mu0[0] *= GasConstant * temperature();
319 }
320 //====================================================================================================================
321 /*
322  * Get the nondimensional Enthalpy functions for the species
323  * at their standard states at the current
324  * <I>T</I> and <I>P</I> of the solution.
325  * Molar enthalpy. Units: J/kmol. For an incompressible,
326  * stoichiometric substance, the internal energy is
327  * independent of pressure, and therefore the molar enthalpy
328  * is \f[ \hat h(T, P) = \hat u(T) + P \hat v \f], where the
329  * molar specific volume is constant.
330  */
331 void MetalSHEelectrons::getEnthalpy_RT(doublereal* hrt) const
332 {
333  getEnthalpy_RT_ref(hrt);
334 }
335 //====================================================================================================================
336 /*
337  * Get the array of nondimensional Entropy functions for the
338  * standard state species
339  * at the current <I>T</I> and <I>P</I> of the solution.
340  */
341 void MetalSHEelectrons::getEntropy_R(doublereal* sr) const
342 {
343  getEntropy_R_ref(sr);
344  doublereal tmp = log(pressure() / m_p0);
345  sr[0] -= tmp;
346 }
347 //====================================================================================================================
348 /*
349  * Get the nondimensional Gibbs functions for the species
350  * at their standard states of solution at the current T and P
351  * of the solution
352  */
353 void MetalSHEelectrons::getGibbs_RT(doublereal* grt) const
354 {
355  getGibbs_RT_ref(grt);
356  doublereal tmp = log(pressure() / m_p0);
357  grt[0] += tmp;
358 }
359 //====================================================================================================================
360 /*
361  * Get the nondimensional Gibbs functions for the standard
362  * state of the species at the current T and P.
363  */
364 void MetalSHEelectrons::getCp_R(doublereal* cpr) const
365 {
366  _updateThermo();
367  cpr[0] = m_cp0_R[0];
368 }
369 //====================================================================================================================
370 /*
371  * Molar internal energy (J/kmol).
372  * For an incompressible,
373  * stoichiometric substance, the molar internal energy is
374  * independent of pressure. Since the thermodynamic properties
375  * are specified by giving the standard-state enthalpy, the
376  * term \f$ P_0 \hat v\f$ is subtracted from the specified molar
377  * enthalpy to compute the molar internal energy.
378  */
379 void MetalSHEelectrons::getIntEnergy_RT(doublereal* urt) const
380 {
381  getEnthalpy_RT(urt);
382  urt[0] -= 1.0;
383 }
384 //====================================================================================================================
385 /*
386  * ---- Thermodynamic Values for the Species Reference States ----
387  */
388 /*
389  * Molar internal energy or the reference state at the current
390  * temperature, T (J/kmol).
391  * For an incompressible,
392  * stoichiometric substance, the molar internal energy is
393  * independent of pressure. Since the thermodynamic properties
394  * are specified by giving the standard-state enthalpy, the
395  * term \f$ P_0 \hat v\f$ is subtracted from the specified molar
396  * enthalpy to compute the molar internal energy.
397  *
398  * Note, this is equal to the standard state internal energy
399  * evaluated at the reference pressure.
400  */
401 void MetalSHEelectrons::getIntEnergy_RT_ref(doublereal* urt) const
402 {
403  _updateThermo();
404  doublereal RT = GasConstant * temperature();
405  doublereal PV = m_p0 / molarDensity();
406  urt[0] = m_h0_RT[0] - PV / RT;
407 }
408 
409 /*
410  * ---- Saturation Properties
411  */
412 
413 
414 
415 /*
416  * ---- Initialization and Internal functions
417  */
418 //====================================================================================================================
419 /*
420  * @internal Initialize. This method is provided to allow
421  * subclasses to perform any initialization required after all
422  * species have been added. For example, it might be used to
423  * resize internal work arrays that must have an entry for
424  * each species. The base class implementation does nothing,
425  * and subclasses that do not require initialization do not
426  * need to overload this method. When importing a CTML phase
427  * description, this method is called just prior to returning
428  * from function importPhase.
429  *
430  * @see importCTML.cpp
431  */
433 {
434  /*
435  * Call the base class thermo initializer
436  */
438 }
439 //====================================================================================================================
440 
441 void MetalSHEelectrons::initThermoXML(XML_Node& phaseNode, std::string id)
442 {
443  /*
444  * Find the Thermo XML node
445  */
446  if (!phaseNode.hasChild("thermo")) {
447  throw CanteraError("MetalSHEelectrons::initThermoXML",
448  "no thermo XML node");
449  }
450  XML_Node& tnode = phaseNode.child("thermo");
451  doublereal dens = 2.65E3;
452  if (tnode.hasChild("density")) {
453  dens = ctml::getFloatDefaultUnits(tnode, "density", "kg/m3");
454  }
455  setDensity(dens);
456  SingleSpeciesTP::initThermoXML(phaseNode, id);
457 }
458 //====================================================================================================================
460 {
461  XML_Node* xtop = new XML_Node("ctml", 0);
462  XML_Node& xv = xtop->addChild("validate");
463  xv.addAttribute("reactions", "yes");
464  xv.addAttribute("species", "yes");
465 
466  XML_Node& xp = xtop->addChild("phase");
467  xp.addAttribute("dim", "3");
468  xp.addAttribute("id", "MetalSHEelectrons");
469  XML_Node& xe = xp.addChild("elementArray", "E");
470  xe.addAttribute("datasrc", "elements.xml");
471  XML_Node& xs = xp.addChild("speciesArray", "she_electron");
472  xs.addAttribute("datasrc", "#species_Metal_SHEelectrons");
473  XML_Node& xt = xp.addChild("thermo");
474  xt.addAttribute("model", "metalSHEelectrons");
475  XML_Node& xtr = xp.addChild("transport");
476  xtr.addAttribute("model", "none");
477  XML_Node& xk = xp.addChild("kinetics");
478  xk.addAttribute("model", "none");
479 
480  XML_Node& xsd = xtop->addChild("speciesData");
481  xsd.addAttribute("id", "species_Metal_SHEelectrons");
482 
483  XML_Node& xsp = xsd.addChild("species");
484  xsp.addAttribute("name", "she_electron");
485  xsp.addChild("atomArray", "E:1");
486  xsp.addChild("charge", "-1");
487  XML_Node& xspt = xsp.addChild("thermo");
488 
489  XML_Node& xN1 = xspt.addChild("NASA");
490  xN1.addAttribute("Tmax", "1000.");
491  xN1.addAttribute("Tmin", "200.");
492  xN1.addAttribute("P0", "100000.0");
493  XML_Node& xF1 = xsd.addChild("floatArray",
494  "1.172165560E+00, 3.990260375E-03, -9.739075500E-06, "
495  "1.007860470E-08, -3.688058805E-12, -4.589675865E+02, 3.415051190E-01");
496  xF1.addAttribute("name", "coeffs");
497  xF1.addAttribute("size", "7");
498 
499  XML_Node& xN2 = xspt.addChild("NASA");
500  xN2.addAttribute("Tmax", "6000.");
501  xN2.addAttribute("Tmin", "1000.");
502  xN2.addAttribute("P0", "100000.0");
503  XML_Node& xF2 = xsd.addChild("floatArray",
504  "1.466432895E+00, 4.133039835E-04, -7.320116750E-08, 7.705017950E-12,"
505  "-3.444022160E-16, -4.065327985E+02, -5.121644350E-01");
506  xF2.addAttribute("name", "coeffs");
507  xF2.addAttribute("size", "7");
508 
509  return xtop;
510 }
511 //====================================================================================================================
512 /*
513  * setParameters:
514  *
515  * Generic routine that is used to set the parameters used
516  * by this model.
517  * C[0] = density of phase [ kg/m3 ]
518  */
519 void MetalSHEelectrons::setParameters(int n, doublereal* const c)
520 {
521  doublereal rho = c[0];
522  setDensity(rho);
523 }
524 //====================================================================================================================
525 /*
526  * getParameters:
527  *
528  * Generic routine that is used to get the parameters used
529  * by this model.
530  * n = 1
531  * C[0] = density of phase [ kg/m3 ]
532  */
533 void MetalSHEelectrons::getParameters(int& n, doublereal* const c) const
534 {
535  doublereal rho = density();
536  n = 1;
537  c[0] = rho;
538 }
539 //====================================================================================================================
540 /*
541  * Reads an xml data block for the parameters needed by this
542  * routine. eosdata is a reference to the xml thermo block, and looks
543  * like this:
544  *
545  * <phase id="stoichsolid" >
546  * <thermo model="StoichSubstance">
547  * <density units="g/cm3">3.52</density>
548  * </thermo>
549  * </phase>
550  */
552 {
553  std::string model = eosdata["model"];
554  if (model != "MetalSHEelectrons") {
555  throw CanteraError("MetalSHEelectrons::setParametersFromXML",
556  "thermo model attribute must be MetalSHEelectrons");
557  }
558  doublereal rho = 2.65E3;
559  if (eosdata.hasChild("density")) {
560  rho = ctml::getFloat(eosdata, "density", "toSI");
561  }
562  setDensity(rho);
563 }
564 //====================================================================================================================
565 
566 }