00001 /** 00002 * @file IdealSolidSolnPhase.cpp 00003 * Implementation file for an ideal solid solution model 00004 * with incompressible thermodynamics (see \ref thermoprops and 00005 * \link Cantera::IdealSolidSolnPhase IdealSolidSolnPhase\endlink). 00006 */ 00007 /* 00008 * $Id: IdealSolidSolnPhase.cpp 398 2010-02-09 20:24:11Z hkmoffa $ 00009 */ 00010 /* 00011 * Copywrite 2006 Sandia Corporation. Under the terms of Contract 00012 * DE-AC04-94AL85000, with Sandia Corporation, the U.S. Government 00013 * retains certain rights in this software. 00014 */ 00015 00016 #include "IdealSolidSolnPhase.h" 00017 #include <iostream> 00018 using namespace std; 00019 00020 namespace Cantera { 00021 00022 /* 00023 * Constructor for IdealSolidSolnPhase class: 00024 * The default form for the generalized concentrations is 0 00025 * i.e., unity. 00026 */ 00027 IdealSolidSolnPhase::IdealSolidSolnPhase(int formGC) : 00028 ThermoPhase(), 00029 m_formGC(formGC), 00030 m_mm(0), 00031 m_tmin(0.0), 00032 m_tmax(1000000.), 00033 m_Pref(OneAtm), 00034 m_Pcurrent(OneAtm), 00035 m_tlast(0.0) 00036 { 00037 if (formGC < 0 || formGC > 2) { 00038 throw CanteraError(" IdealSolidSolnPhase Constructor", 00039 " Illegal value of formGC"); 00040 } 00041 } 00042 00043 IdealSolidSolnPhase::IdealSolidSolnPhase(std::string inputFile, std::string id, 00044 int formGC) : 00045 ThermoPhase(), 00046 m_formGC(formGC), 00047 m_mm(0), 00048 m_tmin(0.0), 00049 m_tmax(1000000.), 00050 m_Pref(OneAtm), 00051 m_Pcurrent(OneAtm), 00052 m_tlast(0.0) 00053 { 00054 if (formGC < 0 || formGC > 2) { 00055 throw CanteraError(" IdealSolidSolnPhase Constructor", 00056 " Illegal value of formGC"); 00057 } 00058 constructPhaseFile(inputFile, id); 00059 } 00060 00061 IdealSolidSolnPhase::IdealSolidSolnPhase(XML_Node& root, std::string id, 00062 int formGC) : 00063 ThermoPhase(), 00064 m_formGC(formGC), 00065 m_mm(0), 00066 m_tmin(0.0), 00067 m_tmax(1000000.), 00068 m_Pref(OneAtm), 00069 m_Pcurrent(OneAtm), 00070 m_tlast(0.0) 00071 { 00072 if (formGC < 0 || formGC > 2) { 00073 throw CanteraError(" IdealSolidSolnPhase Constructor", 00074 " Illegal value of formGC"); 00075 } 00076 constructPhaseXML(root, id); 00077 } 00078 00079 IdealSolidSolnPhase::IdealSolidSolnPhase(const IdealSolidSolnPhase &b) 00080 { 00081 *this = b; 00082 } 00083 00084 00085 IdealSolidSolnPhase& IdealSolidSolnPhase:: 00086 operator=(const IdealSolidSolnPhase &b) { 00087 if (this != &b) { 00088 //ThermoPhase::operator=(b); 00089 // m_spthermo = dupMyselfAsSpeciesThermo(b.m_spthermo); 00090 m_formGC = b.m_formGC; 00091 m_mm = b.m_mm; 00092 m_tmin = b.m_tmin; 00093 m_tmax = b.m_tmax; 00094 m_Pref = b.m_Pref; 00095 m_Pcurrent = b.m_Pcurrent; 00096 m_speciesMolarVolume = b.m_speciesMolarVolume; 00097 m_tlast = b.m_tlast; 00098 m_h0_RT = b.m_h0_RT; 00099 m_cp0_R = b.m_cp0_R; 00100 m_g0_RT = b.m_g0_RT; 00101 m_s0_R = b.m_s0_R; 00102 m_expg0_RT = b.m_expg0_RT; 00103 m_pe = b.m_pe; 00104 m_pp = b.m_pp; 00105 } 00106 return *this; 00107 } 00108 00109 /* 00110 * Base Class Duplication Function 00111 * -> given a pointer to ThermoPhase, this function can 00112 * duplicate the object. (note has to be a separate function 00113 * not the copy constructor, because it has to be 00114 * a virtual function) 00115 */ 00116 ThermoPhase* IdealSolidSolnPhase::duplMyselfAsThermoPhase() const { 00117 IdealSolidSolnPhase *ii = new IdealSolidSolnPhase(*this); 00118 return (ThermoPhase*) ii; 00119 } 00120 00121 /** 00122 * Equation of state flag. Returns the value cIdealGas, defined 00123 * in mix_defs.h. 00124 */ 00125 int IdealSolidSolnPhase::eosType() const { 00126 integer res; 00127 switch (m_formGC) { 00128 case 0: 00129 res = cIdealSolidSolnPhase0; 00130 break; 00131 case 1: 00132 res = cIdealSolidSolnPhase1; 00133 break; 00134 case 2: 00135 res = cIdealSolidSolnPhase2; 00136 break; 00137 default: 00138 throw CanteraError("eosType", "Unknown type"); 00139 break; 00140 } 00141 return res; 00142 } 00143 00144 /******************************************************************** 00145 * Molar Thermodynamic Properties of the Solution 00146 ********************************************************************/ 00147 /** 00148 * Molar enthalpy of the solution. Units: J/kmol. 00149 * For an ideal, constant partial molar volume solution mixture with 00150 * pure species phases which exhibit zero volume expansivity and 00151 * zero isothermal compressibility: 00152 * \f[ 00153 * \hat h(T,P) = \sum_k X_k \hat h^0_k(T) + (P - P_{ref}) (\sum_k X_k \hat V^0_k) 00154 * \f] 00155 * The reference-state pure-species enthalpies at the reference pressure Pref 00156 * \f$ \hat h^0_k(T) \f$, are computed by the species thermodynamic 00157 * property manager. They are polynomial functions of temperature. 00158 * @see SpeciesThermo 00159 */ 00160 doublereal IdealSolidSolnPhase:: 00161 enthalpy_mole() const { 00162 const double *eptr = &(enthalpy_RT_ref()[0]); 00163 doublereal htp = (GasConstant * temperature() * mean_X(eptr)); 00164 return (htp + (pressure() - m_Pref)/molarDensity()); 00165 } 00166 00167 /** 00168 * Molar internal energy of the solution. J/kmol. 00169 * For an ideal, constant partial molar volume solution mixture with 00170 * pure species phases which exhibit zero volume expansivity and 00171 * zero isothermal compressibility: 00172 * \f[ 00173 * \hat u(T) = \hat h(T,P) - p \hat V = \sum_k X_k \hat h^0_k(T) 00174 * - P_{ref} (\sum_k X_k \hat V^0_k) 00175 * \f] 00176 * and is a function only of temperature. 00177 * The reference-state pure-species enthalpies 00178 * \f$ \hat h^0_k(T) \f$ are computed by the species thermodynamic 00179 * property manager. 00180 * @see SpeciesThermo 00181 */ 00182 doublereal IdealSolidSolnPhase::intEnergy_mole() const { 00183 const double *eptr = DATA_PTR(enthalpy_RT_ref().begin()); 00184 doublereal htp = (GasConstant * temperature() * 00185 mean_X(eptr)); 00186 return (htp - m_Pref / molarDensity()); 00187 } 00188 00189 /** 00190 * Molar entropy of the solution. Units: J/kmol/K. 00191 * For an ideal, constant partial molar volume solution mixture with 00192 * pure species phases which exhibit zero volume expansivity: 00193 * \f[ 00194 * \hat s(T, P, X_k) = \sum_k X_k \hat s^0_k(T) 00195 * - \hat R \sum_k X_k log(X_k) 00196 * \f] 00197 * The reference-state pure-species entropies 00198 * \f$ \hat s^0_k(T,p_{ref}) \f$ are computed by the species thermodynamic 00199 * property manager. The pure species entropies are independent of 00200 * temperature since the volume expansivities are equal to zero. 00201 * @see SpeciesThermo 00202 */ 00203 doublereal IdealSolidSolnPhase::entropy_mole() const { 00204 const double *dptr = DATA_PTR(entropy_R_ref()); 00205 return GasConstant * (mean_X(dptr) - sum_xlogx()); 00206 } 00207 00208 /** 00209 * Molar gibbs free energy of the solution. Units: J/kmol. 00210 * For an ideal, constant partial molar volume solution mixture with 00211 * pure species phases which exhibit zero volume expansivity: 00212 * \f[ 00213 * \hat g(T, P) = \sum_k X_k \hat g^0_k(T,P) + \hat R T \sum_k X_k log(X_k) 00214 * \f] 00215 * The reference-state pure-species gibbs free energies 00216 * \f$ \hat g^0_k(T) \f$ are computed by the species thermodynamic 00217 * property manager, while the standard state gibbs free energies 00218 * \f$ \hat g^0_k(T,P) \f$ are computed by the member function, gibbs_RT(). 00219 * @see SpeciesThermo 00220 */ 00221 doublereal IdealSolidSolnPhase::gibbs_mole() const { 00222 const double *dptr = DATA_PTR(gibbs_RT_ref()); 00223 doublereal g = mean_X(dptr); 00224 return (GasConstant * temperature() * (g + sum_xlogx())); 00225 } 00226 00227 /** 00228 * Molar heat capacity at constant pressure of the solution. 00229 * Units: J/kmol/K. 00230 * For an ideal, constant partial molar volume solution mixture with 00231 * pure species phases which exhibit zero volume expansivity: 00232 * \f[ 00233 * \hat c_p(T,P) = \sum_k X_k \hat c^0_{p,k}(T) . 00234 * \f] 00235 * The heat capacity is independent of pressure. 00236 * The reference-state pure-species heat capacities 00237 * \f$ \hat c^0_{p,k}(T) \f$ are computed by the species thermodynamic 00238 * property manager. 00239 * @see SpeciesThermo 00240 */ 00241 doublereal IdealSolidSolnPhase::cp_mole() const { 00242 const double *dptr = DATA_PTR(cp_R_ref()); 00243 return GasConstant * mean_X(dptr); 00244 } 00245 00246 /******************************************************************** 00247 * Mechanical Equation of State 00248 ********************************************************************/ 00249 /** 00250 * 00251 * Calculate the density of the mixture using the partial 00252 * molar volumes and mole fractions as input 00253 * 00254 * The formula for this is 00255 * 00256 * \f[ 00257 * \rho = \frac{\sum_k{X_k W_k}}{\sum_k{X_k V_k}} 00258 * \f] 00259 * 00260 * where \f$ X_k \f$ are the mole fractions, \f$W_k\f$ are 00261 * the molecular weights, and \f$V_k\f$ are the pure species 00262 * molar volumes. 00263 * 00264 * Note, the basis behind this formula is that in an ideal 00265 * solution the partial molar volumes are equal to the pure 00266 * species molar volumes. We have additionally specified that 00267 * in this class that the pure species molar volumes are 00268 * independent of temperature and pressure. 00269 */ 00270 void IdealSolidSolnPhase::calcDensity() { 00271 /* 00272 * Calculate the molarVolume of the solution (m**3 kmol-1) 00273 */ 00274 const doublereal * const dtmp = moleFractdivMMW(); 00275 double invDens = dot(m_speciesMolarVolume.begin(), 00276 m_speciesMolarVolume.end(), dtmp); 00277 /* 00278 * Set the density in the parent State object directly, 00279 * by calling the State::setDensity() function. 00280 */ 00281 double dens = 1.0/invDens; 00282 State::setDensity(dens); 00283 } 00284 00285 /** 00286 * Overwritten setDensity() function is necessary because the 00287 * density is not an indendent variable. 00288 * 00289 * This function will now throw an error condition 00290 * 00291 * @internal May have to adjust the strategy here to make 00292 * the eos for these materials slightly compressible, in order 00293 * to create a condition where the density is a function of 00294 * the pressure. 00295 * 00296 * This function will now throw an error condition. 00297 * 00298 * NOTE: This is a virtual function that overwrites the State.h 00299 * class 00300 */ 00301 void IdealSolidSolnPhase:: 00302 setDensity(const doublereal rho) { 00303 /* 00304 * Unless the input density is exactly equal to the density 00305 * calculated and storred in the State object, we throw an 00306 * exception. This is because the density is NOT an 00307 * independent variable. 00308 */ 00309 double dens = density(); 00310 if (rho != dens) { 00311 throw CanteraError("IdealSolidSolnPhase::setDensity", 00312 "Density is not an independent variable"); 00313 } 00314 } 00315 00316 /* 00317 * setPressure(double) (virtual from ThermoPhase) 00318 * 00319 * Set the pressure at constant temperature. Units: Pa. 00320 * This method sets a constant within the object. 00321 * The mass density is not a function of pressure. 00322 * Note: This function overrides the setPressure() function 00323 * in the ThermoPhase object. 00324 * We calculate the density and store it in the 00325 * State object, because this density is supposed to 00326 * be current after setting the pressure, and is now 00327 * a dependent variable. 00328 */ 00329 void IdealSolidSolnPhase::setPressure(doublereal p) { 00330 m_Pcurrent = p; 00331 calcDensity(); 00332 } 00333 00334 /* 00335 * setMolarDensity() (virtual from State) 00336 * Overwritten setMolarDensity() function is necessary because the 00337 * density is not an indendent variable. 00338 * 00339 * This function will now throw an error condition. 00340 * 00341 * NOTE: This is a virtual function that overrides the State.h 00342 * class 00343 */ 00344 void IdealSolidSolnPhase::setMolarDensity(const doublereal n) { 00345 throw CanteraError("IdealSolidSolnPhase::setMolarDensity", 00346 "Density is not an independent variable"); 00347 } 00348 00349 /* 00350 * setMoleFractions() (virtual from State) 00351 * 00352 * Sets the mole fractions and adjusts the internal density. 00353 */ 00354 void IdealSolidSolnPhase::setMoleFractions(const doublereal * const x) { 00355 State::setMoleFractions(x); 00356 calcDensity(); 00357 } 00358 00359 /** 00360 * setMoleFractions_NoNorm() (virtual from State) 00361 * 00362 * Sets the mole fractions and adjusts the internal density. 00363 */ 00364 void IdealSolidSolnPhase::setMoleFractions_NoNorm(const doublereal * const x) { 00365 State::setMoleFractions(x); 00366 calcDensity(); 00367 } 00368 00369 /* 00370 * setMassFractions() (virtual from State) 00371 * 00372 * Sets the mass fractions and adjusts the internal density. 00373 */ 00374 void IdealSolidSolnPhase::setMassFractions(const doublereal * const y) { 00375 State::setMassFractions(y); 00376 calcDensity(); 00377 } 00378 00379 /* 00380 * setMassFractions_NoNorm() (virtual from State) 00381 * 00382 * Sets the mass fractions and adjusts the internal density. 00383 */ 00384 void IdealSolidSolnPhase::setMassFractions_NoNorm(const doublereal * const y) { 00385 State::setMassFractions_NoNorm(y); 00386 calcDensity(); 00387 } 00388 00389 /* 00390 * setConcentrations (virtual from State) 00391 * 00392 * Sets the concentrations and adjusts the internal density 00393 */ 00394 void IdealSolidSolnPhase::setConcentrations(const doublereal * const c) { 00395 State::setConcentrations(c); 00396 calcDensity(); 00397 } 00398 00399 /******************************************************************** 00400 * Chemical Potentials and Activities 00401 ********************************************************************/ 00402 00403 /******************************************************************** 00404 * 00405 * getActivitConcentrations(): 00406 * 00407 * This method returns the array of generalized 00408 * concentrations. The generalized concentrations are used 00409 * in the evaluation of the rates of progress for reactions 00410 * involving species in this phase. The generalized 00411 * concentration dividied by the standard concentration is also 00412 * equal to the activity of species. 00413 * 00414 * For this implentation the activity is defined to be the 00415 * mole fraction of the species. The generalized concentration 00416 * is defined to be equal to the mole fraction divided by 00417 * the partial molar volume. The generalized concentrations 00418 * for species in this phase therefore have units of 00419 * kmol m<SUP>-3</SUP>. Rate constants must reflect this fact. 00420 * 00421 * On a general note, the following must be true. 00422 * For an ideal solution, the generalized concentration must consist 00423 * of the mole fraction multiplied by a constant. The constant may be 00424 * fairly arbitrarily chosen, with differences adsorbed into the 00425 * reaction rate expression. 1/V_N, 1/V_k, or 1 are equally good, 00426 * as long as the standard concentration is adjusted accordingly. 00427 * However, it must be a constant (and not the concentration, btw, 00428 * which is a function of the mole fractions) in order for the 00429 * ideal solution properties to hold at the same time having the 00430 * standard concentration to be independent of the mole fractions. 00431 * 00432 * In this implementation the form of the generalized concentrations 00433 * depend upon the member attribute, m_formGC: 00434 * 00435 * <TABLE> 00436 * <TR><TD> m_formGC </TD><TD> GeneralizedConc </TD><TD> StandardConc </TD></TR> 00437 * <TR><TD> 0 </TD><TD> X_k </TD><TD> 1.0 </TD></TR> 00438 * <TR><TD> 1 </TD><TD> X_k / V_k </TD><TD> 1.0 / V_k </TD></TR> 00439 * <TR><TD> 2 </TD><TD> X_k / V_N </TD><TD> 1.0 / V_N </TD></TR> 00440 * </TABLE> 00441 * 00442 * HKM Note: We have absorbed the pressure dependence of the pure species 00443 * state into the thermodynamics functions. Therefore the 00444 * standard state on which the activities are based depend 00445 * on both temperature and pressure. If we hadn't, it would have 00446 * appeared in this function in a very awkwards exp[] format. 00447 * 00448 * @param c[] Pointer to array of doubles of length m_kk, which on exit 00449 * will contain the generalized concentrations. 00450 */ 00451 void IdealSolidSolnPhase:: 00452 getActivityConcentrations(doublereal* c) const { 00453 const doublereal * const dtmp = moleFractdivMMW(); 00454 const double mmw = meanMolecularWeight(); 00455 switch (m_formGC) { 00456 case 0: 00457 for (int k = 0; k < m_kk; k++) { 00458 c[k] = dtmp[k] * mmw; 00459 } 00460 break; 00461 case 1: 00462 for (int k = 0; k < m_kk; k++) { 00463 c[k] = dtmp[k] * mmw / m_speciesMolarVolume[k]; 00464 } 00465 break; 00466 case 2: 00467 double atmp = mmw / m_speciesMolarVolume[m_kk-1]; 00468 for (int k = 0; k < m_kk; k++) { 00469 c[k] = dtmp[k] * atmp; 00470 } 00471 break; 00472 } 00473 } 00474 00475 /********************************************************************* 00476 * 00477 * standardConcentration() 00478 * 00479 * The standard concentration \f$ C^0_k \f$ used to normalize 00480 * the generalized concentration. 00481 * In many cases, this quantity 00482 * will be the same for all species in a phase. 00483 * However, for this case, we will return a distinct concentration 00484 * for each species. This is the inverse of the species molar 00485 * volume. Units are m<SUP>3</SUP> kmol<SUP>-1</SUP>. 00486 * 00487 * 00488 * @param k Species number: this is a require parameter, 00489 * a change from the ThermoPhase base class, where it was 00490 * an optional parameter. 00491 */ 00492 doublereal IdealSolidSolnPhase:: 00493 standardConcentration(int k) const { 00494 switch (m_formGC) { 00495 case 0: 00496 return 1.0; 00497 case 1: 00498 return 1.0 / m_speciesMolarVolume[k]; 00499 case 2: 00500 return 1.0/m_speciesMolarVolume[m_kk-1]; 00501 } 00502 return 0.0; 00503 } 00504 doublereal IdealSolidSolnPhase:: 00505 referenceConcentration(int k) const { 00506 switch (m_formGC) { 00507 case 0: 00508 return 1.0; 00509 case 1: 00510 return 1.0 / m_speciesMolarVolume[k]; 00511 case 2: 00512 return 1.0 / m_speciesMolarVolume[m_kk-1]; 00513 } 00514 return 0.0; 00515 } 00516 00517 /********************************************************************* 00518 * 00519 * logStandardConc() 00520 * 00521 * Returns the log of the standard concentration 00522 * 00523 * @param k Species number: this is a require parameter, 00524 * a change from the ThermoPhase base class, where it was 00525 * an optional parameter. 00526 */ 00527 doublereal IdealSolidSolnPhase:: 00528 logStandardConc(int k) const { 00529 _updateThermo(); 00530 double res; 00531 switch (m_formGC) { 00532 case 0: 00533 res = 0.0; 00534 break; 00535 case 1: 00536 res = log(1.0/m_speciesMolarVolume[k]); 00537 break; 00538 case 2: 00539 res = log(1.0/m_speciesMolarVolume[m_kk-1]); 00540 break; 00541 default: 00542 throw CanteraError("eosType", "Unknown type"); 00543 break; 00544 } 00545 return res; 00546 } 00547 00548 /*********************************************************************** 00549 * 00550 * getUnitsStandardConcentration() 00551 * 00552 * Returns the units of the standard and general concentrations 00553 * Note they have the same units, as their divisor is 00554 * defined to be equal to the activity of the kth species 00555 * in the solution, which is unitless. 00556 * 00557 * This routine is used in print out applications where the 00558 * units are needed. Usually, MKS units are assumed throughout 00559 * the program and in the XML input files. 00560 * 00561 * uA[0] = kmol units - default = 1 00562 * uA[1] = m units - default = -nDim(), the number of spatial 00563 * dimensions in the Phase class. 00564 * uA[2] = kg units - default = 0; 00565 * uA[3] = Pa(pressure) units - default = 0; 00566 * uA[4] = Temperature units - default = 0; 00567 * uA[5] = time units - default = 0 00568 * 00569 * For EOS types other than cIdealSolidSolnPhase1, the default 00570 * kmol/m3 holds for standard concentration units. For 00571 * cIdealSolidSolnPhase0 type, the standard concentrtion is 00572 * unitless. 00573 */ 00574 void IdealSolidSolnPhase:: 00575 getUnitsStandardConc(double *uA, int, int sizeUA) const { 00576 int eos = eosType(); 00577 if (eos == cIdealSolidSolnPhase0) { 00578 for (int i = 0; i < sizeUA; i++) { 00579 uA[i] = 0.0; 00580 } 00581 } else { 00582 for (int i = 0; i < sizeUA; i++) { 00583 if (i == 0) uA[0] = 1.0; 00584 if (i == 1) uA[1] = -nDim(); 00585 if (i == 2) uA[2] = 0.0; 00586 if (i == 3) uA[3] = 0.0; 00587 if (i == 4) uA[4] = 0.0; 00588 if (i == 5) uA[5] = 0.0; 00589 } 00590 } 00591 } 00592 00593 /* 00594 * getActivityCoefficients(): 00595 * 00596 */ 00597 void IdealSolidSolnPhase:: 00598 getActivityCoefficients(doublereal *ac) const { 00599 for (int k = 0; k < m_kk; k++) { 00600 ac[k] = 1.0; 00601 } 00602 } 00603 //================================================================================================ 00604 /* 00605 * 00606 * getChemPotentials(): 00607 * 00608 * This function returns a vector of chemical potentials of the 00609 * species. 00610 * \f[ 00611 * \mu_k = \mu^o_k(T) + V_k * (p - p_o) + R T ln(X_k) 00612 * \f] 00613 * or another way to phrase this is 00614 * \f[ 00615 * \mu_k = \mu^o_k(T,p) + R T ln(X_k) 00616 * \f] 00617 * where \f$ \mu^o_k(T,p) = \mu^o_k(T) + V_k * (p - p_o)\f$ 00618 * 00619 */ 00620 void IdealSolidSolnPhase:: 00621 getChemPotentials(doublereal* mu) const { 00622 doublereal delta_p = m_Pcurrent - m_Pref; 00623 doublereal xx; 00624 doublereal RT = temperature() * GasConstant; 00625 const array_fp& g_RT = gibbs_RT_ref(); 00626 for (int k = 0; k < m_kk; k++) { 00627 xx = fmaxx(SmallNumber, moleFraction(k)); 00628 mu[k] = RT * (g_RT[k] + log(xx)) 00629 + delta_p * m_speciesMolarVolume[k]; 00630 } 00631 } 00632 //================================================================================================ 00633 /* 00634 * 00635 * getChemPotentials_RT() 00636 * 00637 * Get the array of non-dimensional chemical potentials \f$ 00638 * \mu_k / \hat R T \f$, where 00639 * 00640 * \f[ 00641 * \mu_k = \mu^o_k(T) + V_k * (p - p_o) + R T ln(X_k) 00642 * \f] 00643 * or another way to phrase this is 00644 * \f[ 00645 * \mu_k = \mu^o_k(T,p) + R T ln(X_k) 00646 * \f] 00647 * where \f$ \mu^o_k(T,p) = \mu^o_k(T) + V_k * (p - p_o)\f$ 00648 * 00649 */ 00650 void IdealSolidSolnPhase:: 00651 getChemPotentials_RT(doublereal* mu) const { 00652 doublereal RT = temperature() * GasConstant; 00653 doublereal delta_pdRT = (m_Pcurrent - m_Pref) / RT; 00654 doublereal xx; 00655 const array_fp& g_RT = gibbs_RT_ref(); 00656 for (int k = 0; k < m_kk; k++) { 00657 xx = fmaxx(SmallNumber, moleFraction(k)); 00658 mu[k] = (g_RT[k] + log(xx)) 00659 + delta_pdRT * m_speciesMolarVolume[k]; 00660 } 00661 } 00662 00663 /******************************************************************** 00664 * Partial Molar Properties 00665 ********************************************************************/ 00666 00667 /******************************************************************** 00668 * 00669 * getPartialMolarEnthalpies() 00670 * 00671 * For this phase, the partial molar enthalpies are equal to the 00672 * pure species enthalpies. 00673 * \f[ 00674 * \hat h_k(T,P) = \sum_k X_k \hat h^0_k(T) + (p - p_{ref}) (\sum_k X_k \hat V^0_k) 00675 * \f] 00676 * The reference-state pure-species enthalpies at the reference 00677 * pressure p_ref 00678 * \f$ \hat h^0_k(T) \f$, are computed by the species thermodynamic 00679 * property manager. They are polynomial functions of temperature. 00680 * @see SpeciesThermo 00681 */ 00682 void IdealSolidSolnPhase:: 00683 getPartialMolarEnthalpies(doublereal* hbar) const { 00684 const array_fp& _h = enthalpy_RT_ref(); 00685 doublereal rt = GasConstant * temperature(); 00686 scale(_h.begin(), _h.end(), hbar, rt); 00687 } 00688 00689 /******************************************************************** 00690 * 00691 * getPartialMolarEntropies() 00692 * 00693 * Returns an array of partial molar entropies of the species in the 00694 * solution. Units: J/kmol. 00695 * For this phase, the partial molar entropies are equal to the 00696 * pure species entropies plus the ideal solution contribution. 00697 * \f[ 00698 * \bar s_k(T,P) = \hat s^0_k(T) - R log(X_k) 00699 * \f] 00700 * The reference-state pure-species entropies,\f$ \hat s^0_k(T) \f$, 00701 * at the reference pressure, \f$ P_{ref} \f$, are computed by the 00702 * species thermodynamic 00703 * property manager. They are polynomial functions of temperature. 00704 * @see SpeciesThermo 00705 */ 00706 void IdealSolidSolnPhase:: 00707 getPartialMolarEntropies(doublereal* sbar) const { 00708 const array_fp& _s = entropy_R_ref(); 00709 doublereal r = GasConstant; 00710 doublereal xx; 00711 for (int k = 0; k < m_kk; k++) { 00712 xx = fmaxx(SmallNumber, moleFraction(k)); 00713 sbar[k] = r * (_s[k] - log(xx)); 00714 } 00715 } 00716 00717 /******************************************************************** 00718 * 00719 * getPartialMolarCp() 00720 * 00721 * For this phase, the partial molar heat capacities are equal 00722 * to the standard state heat capacities. 00723 00724 */ 00725 void IdealSolidSolnPhase:: 00726 getPartialMolarCp(doublereal* cpbar) const { 00727 getCp_R(cpbar); 00728 for (int k = 0; k < m_kk; k++) { 00729 cpbar[k] *= GasConstant; 00730 } 00731 } 00732 00733 /****************************************************************** 00734 * 00735 * getPartialMolarVolumes() 00736 * 00737 * returns an array of partial molar volumes of the species 00738 * in the solution. Units: m^3 kmol-1. 00739 * 00740 * For this solution, thepartial molar volumes are equal to the 00741 * constant species molar volumes. 00742 */ 00743 void IdealSolidSolnPhase:: 00744 getPartialMolarVolumes(doublereal* vbar) const { 00745 getStandardVolumes(vbar); 00746 } 00747 00748 /***************************************************************** 00749 * Properties of the Standard State of the Species 00750 * in the Solution 00751 *****************************************************************/ 00752 00753 /****************************************************************** 00754 * 00755 * getPureGibbs() 00756 * 00757 * Get the Gibbs functions for the pure species 00758 * at the current <I>T</I> and <I>P</I> of the solution. 00759 * We assume an incompressible constant partial molar 00760 * volume here: 00761 * \f[ 00762 * \mu^0_k(T,p) = \mu^{ref}_k(T) + (P - P_{ref}) * V_k 00763 * \f] 00764 * where \f$V_k\f$ is the molar volume of pure species <I>k<\I>. 00765 * \f$ u^{ref}_k(T)\f$ is the chemical potential of pure 00766 * species <I>k<\I> at the reference pressure, \f$P_{ref}\f$. 00767 */ 00768 void IdealSolidSolnPhase:: 00769 getPureGibbs(doublereal* gpure) const { 00770 const array_fp& gibbsrt = gibbs_RT_ref(); 00771 doublereal RT = _RT(); 00772 const doublereal * const gk = DATA_PTR(gibbsrt); 00773 doublereal delta_p = (m_Pcurrent - m_Pref); 00774 for (int k = 0; k < m_kk; k++) { 00775 gpure[k] = RT * gk[k] + delta_p * m_speciesMolarVolume[k]; 00776 } 00777 } 00778 00779 /** 00780 * Get the nondimensional gibbs function for the species 00781 * standard states at the current T and P of the solution. 00782 * 00783 * \f[ 00784 * \mu^0_k(T,P) = \mu^{ref}_k(T) + (P - P_{ref}) * V_k 00785 * \f] 00786 * where \f$V_k\f$ is the molar volume of pure species <I>k</I>. 00787 * \f$ \mu^{ref}_k(T)\f$ is the chemical potential of pure 00788 * species <I>k</I> at the reference pressure, \f$P_{ref}\f$. 00789 * 00790 * @param grt Vector of length m_kk, which on return sr[k] 00791 * will contain the nondimensional 00792 * standard state gibbs function for species k. 00793 */ 00794 void IdealSolidSolnPhase:: 00795 getGibbs_RT(doublereal* grt) const { 00796 const array_fp& gibbsrt = gibbs_RT_ref(); 00797 doublereal RT = _RT(); 00798 const doublereal * const gk = DATA_PTR(gibbsrt); 00799 doublereal delta_prt = (m_Pcurrent - m_Pref)/ RT; 00800 for (int k = 0; k < m_kk; k++) { 00801 grt[k] = gk[k] + delta_prt * m_speciesMolarVolume[k]; 00802 } 00803 } 00804 00805 /******************************************************************** 00806 * 00807 * getEnthalpy_RT() 00808 * 00809 * Get the array of nondimensional Enthalpy functions for the ss 00810 * species at the current <I>T</I> and <I>P</I> of the solution. 00811 * We assume an incompressible constant partial molar 00812 * volume here: 00813 * \f[ 00814 * h^0_k(T,P) = h^{ref}_k(T) + (P - P_{ref}) * V_k 00815 * \f] 00816 * where \f$V_k\f$ is the molar volume of pure species <I>k<\I>. 00817 * \f$ h^{ref}_k(T)\f$ is the enthalpy of the pure 00818 * species <I>k<\I> at the reference pressure, \f$P_{ref}\f$. 00819 */ 00820 void IdealSolidSolnPhase:: 00821 getEnthalpy_RT(doublereal* hrt) const { 00822 const array_fp& _h = enthalpy_RT_ref(); 00823 doublereal delta_prt = ((m_Pcurrent - m_Pref) / 00824 (GasConstant * temperature())); 00825 for (int k = 0; k < m_kk; k++) { 00826 hrt[k] = _h[k] + delta_prt * m_speciesMolarVolume[k]; 00827 } 00828 } 00829 00830 /** 00831 * Get the nondimensional Entropies for the species 00832 * standard states at the current T and P of the solution. 00833 * 00834 * Note, this is equal to the reference state entropies 00835 * due to the zero volume expansivity: 00836 * i.e., (dS/dp)_T = (dV/dT)_P = 0.0 00837 * 00838 * @param sr Vector of length m_kk, which on return sr[k] 00839 * will contain the nondimensional 00840 * standard state entropy of species k. 00841 */ 00842 void IdealSolidSolnPhase::getEntropy_R(doublereal* sr) const { 00843 const array_fp& _s = entropy_R_ref(); 00844 copy(_s.begin(), _s.end(), sr); 00845 } 00846 00847 /* 00848 * Returns the vector of nondimensional 00849 * internal Energies of the standard state at the current temperature 00850 * of the solution and current pressure for each species. 00851 * \f[ 00852 * u^0_k(T,P) = h^{ref}_k(T) - P_{ref} * V_k 00853 * \f] 00854 * 00855 * The standard state internal energy is independent of 00856 * pressure in this equation of state. 00857 * (inherited from ThermoPhase.h) 00858 */ 00859 void IdealSolidSolnPhase::getIntEnergy_RT(doublereal *urt) const { 00860 const array_fp& _h = enthalpy_RT_ref(); 00861 doublereal prefrt = m_Pref / (GasConstant * temperature()); 00862 for (int k = 0; k < m_kk; k++) { 00863 urt[k] = _h[k] - prefrt * m_speciesMolarVolume[k]; 00864 } 00865 } 00866 00867 /* 00868 * Get the nondimensional heat capacity at constant pressure 00869 * function for the species 00870 * standard states at the current T and P of the solution. 00871 * 00872 * \f[ 00873 * Cp^0_k(T,P) = Cp^{ref}_k(T) 00874 * \f] 00875 * where \f$V_k\f$ is the molar volume of pure species <I>k<\I>. 00876 * \f$ Cp^{ref}_k(T)\f$ is the constant pressure heat capacity 00877 * of species <I>k<\I> at the reference pressure, \f$P_{ref}\f$. 00878 * 00879 * @param cpr Vector of length m_kk, which on return cpr[k] 00880 * will contain the nondimensional 00881 * constant pressure heat capacity for species k. 00882 */ 00883 void IdealSolidSolnPhase::getCp_R(doublereal* cpr) const { 00884 const array_fp& _cpr = cp_R_ref(); 00885 copy(_cpr.begin(), _cpr.end(), cpr); 00886 } 00887 00888 /* 00889 * Get the molar volumes of each species in their standard 00890 * states at the current 00891 * <I>T</I> and <I>P</I> of the solution. 00892 * units = m^3 / kmol 00893 */ 00894 void IdealSolidSolnPhase::getStandardVolumes(doublereal *vol) const { 00895 copy(m_speciesMolarVolume.begin(), 00896 m_speciesMolarVolume.end(), vol); 00897 } 00898 00899 00900 /********************************************************************* 00901 * Thermodynamic Values for the Species Reference States 00902 *********************************************************************/ 00903 00904 /* 00905 * Returns the vector of non-dimensional Enthalpy function 00906 * of the reference state at the current temperature 00907 * of the solution and the reference pressure for the species. 00908 * Units = unitless 00909 */ 00910 void IdealSolidSolnPhase::getEnthalpy_RT_ref(doublereal *hrt) const { 00911 _updateThermo(); 00912 for (int k = 0; k != m_kk; k++) { 00913 hrt[k] = m_h0_RT[k]; 00914 } 00915 } 00916 00917 /* 00918 * Returns the vector of non-dimensional Gibbs function 00919 * of the reference state at the current temperature 00920 * of the solution and the reference pressure for the species. 00921 * Units = unitless 00922 */ 00923 void IdealSolidSolnPhase::getGibbs_RT_ref(doublereal *grt) const { 00924 _updateThermo(); 00925 for (int k = 0; k != m_kk; k++) { 00926 grt[k] = m_g0_RT[k]; 00927 } 00928 } 00929 00930 /* 00931 * Returns the vector of Gibbs function 00932 * of the reference state at the current temperature 00933 * of the solution and the reference pressure for the species. 00934 * Units = J / kmol 00935 */ 00936 void IdealSolidSolnPhase::getGibbs_ref(doublereal *g) const { 00937 _updateThermo(); 00938 double tmp = GasConstant * temperature(); 00939 for (int k = 0; k != m_kk; k++) { 00940 g[k] = tmp * m_g0_RT[k]; 00941 } 00942 } 00943 00944 /* 00945 * Returns the vector of nondimensional 00946 * internal Energies of the standard state at the current temperature 00947 * of the solution and current pressure for each species. 00948 * (inherited from ThermoPhase.h) 00949 */ 00950 void IdealSolidSolnPhase::getIntEnergy_RT_ref(doublereal *urt) const { 00951 const array_fp& _h = enthalpy_RT_ref(); 00952 doublereal prefrt = m_Pref / (GasConstant * temperature()); 00953 for (int k = 0; k < m_kk; k++) { 00954 urt[k] = _h[k] - prefrt * m_speciesMolarVolume[k]; 00955 } 00956 } 00957 00958 /* 00959 * Returns the vector of non-dimensional Entropy function 00960 * of the reference state at the current temperature 00961 * of the solution and the reference pressure for the species. 00962 * Units = unitless 00963 */ 00964 void IdealSolidSolnPhase::getEntropy_R_ref(doublereal *er) const { 00965 _updateThermo(); 00966 for (int k = 0; k != m_kk; k++) { 00967 er[k] = m_s0_R[k]; 00968 } 00969 } 00970 00971 /* 00972 * Returns the vector of non-dimensional Entropy function 00973 * of the reference state at the current temperature 00974 * of the solution and the reference pressure for the species. 00975 * Units = unitless 00976 */ 00977 void IdealSolidSolnPhase::getCp_R_ref(doublereal *cpr) const { 00978 _updateThermo(); 00979 for (int k = 0; k != m_kk; k++) { 00980 cpr[k] = m_cp0_R[k]; 00981 } 00982 } 00983 00984 /* 00985 * Returns a reference to the vector of nondimensional 00986 * enthalpies of the reference state at the current temperature. 00987 * Real reason for its existence is that it also checks 00988 * to see if a recalculation of the reference thermodynamics 00989 * functions needs to be done. 00990 */ 00991 const array_fp& IdealSolidSolnPhase::enthalpy_RT_ref() const { 00992 _updateThermo(); 00993 return m_h0_RT; 00994 } 00995 00996 /* 00997 * Returns a reference to the vector of nondimensional 00998 * enthalpies of the reference state at the current temperature. 00999 * Real reason for its existence is that it also checks 01000 * to see if a recalculation of the reference thermodynamics 01001 * functions needs to be done. 01002 */ 01003 const array_fp& IdealSolidSolnPhase::expGibbs_RT_ref() const { 01004 _updateThermo(); 01005 int k; 01006 for (k = 0; k != m_kk; k++) m_expg0_RT[k] = exp(m_g0_RT[k]); 01007 return m_expg0_RT; 01008 } 01009 01010 /* 01011 * Returns a reference to the vector of nondimensional 01012 * enthalpies of the reference state at the current temperature. 01013 * Real reason for its existence is that it also checks 01014 * to see if a recalculation of the reference thermodynamics 01015 * functions needs to be done. 01016 */ 01017 const array_fp& IdealSolidSolnPhase::entropy_R_ref() const { 01018 _updateThermo(); 01019 return m_s0_R; 01020 } 01021 01022 /********************************************************************* 01023 * Utility Functions 01024 *********************************************************************/ 01025 /* 01026 * initThermo() function initializes the object for use. 01027 * 01028 * Before its invokation, the class isn't ready for calculation. 01029 */ 01030 void IdealSolidSolnPhase::initThermo() { 01031 } 01032 01033 /* 01034 * Import and initialize an IdealSolidSolnPhase phase 01035 * specification in an XML tree into the current object. 01036 * Here we read an XML description of the phase. 01037 * We import descriptions of the elements that make up the 01038 * species in a phase. 01039 * We import information about the species, including their 01040 * reference state thermodynamic polynomials. We then freeze 01041 * the state of the species. 01042 * 01043 * This routine calls importPhase() to do most of its work. 01044 * Then, importPhase() calls initThermoXML() to finish 01045 * off the work. 01046 * 01047 * @param phaseNode This object must be the phase node of a 01048 * complete XML tree 01049 * description of the phase, including all of the 01050 * species data. In other words while "phase" must 01051 * point to an XML phase object, it must have 01052 * sibling nodes "speciesData" that describe 01053 * the species in the phase. 01054 * @param id ID of the phase. If nonnull, a check is done 01055 * to see if phaseNode is pointing to the phase 01056 * with the correct id. 01057 */ 01058 void IdealSolidSolnPhase:: 01059 constructPhaseXML(XML_Node& phaseNode, std::string id) { 01060 string subname = "IdealSolidSolnPhase::constructPhaseXML"; 01061 if (id.size() > 0) { 01062 string idp = phaseNode.id(); 01063 if (idp != id) { 01064 throw CanteraError(subname.c_str(), 01065 "phasenode and Id are incompatible"); 01066 } 01067 } 01068 01069 /* 01070 * Check on the thermo field. Must have: 01071 * <thermo model="IdealSolidSolution" /> 01072 */ 01073 if (phaseNode.hasChild("thermo")) { 01074 XML_Node& thNode = phaseNode.child("thermo"); 01075 string mStringa = thNode.attrib("model"); 01076 string mString = lowercase(mStringa); 01077 if (mString != "idealsolidsolution") { 01078 throw CanteraError(subname.c_str(), 01079 "Unknown thermo model: " + mStringa); 01080 } 01081 } else { 01082 throw CanteraError(subname.c_str(), 01083 "Unspecified thermo model"); 01084 } 01085 01086 /* 01087 * Form of the standard concentrations. Must have one of: 01088 * 01089 * <standardConc model="unity" /> 01090 * <standardConc model="molar_volume" /> 01091 * <standardConc model="solvent_volume" /> 01092 */ 01093 if (phaseNode.hasChild("standardConc")) { 01094 XML_Node& scNode = phaseNode.child("standardConc"); 01095 string formStringa = scNode.attrib("model"); 01096 string formString = lowercase(formStringa); 01097 if (formString == "unity") { 01098 m_formGC = 0; 01099 } else if (formString == "molar_volume") { 01100 m_formGC = 1; 01101 } else if (formString == "solvent_volume") { 01102 m_formGC = 2; 01103 } else { 01104 throw CanteraError(subname.c_str(), 01105 "Unknown standardConc model: " + formStringa); 01106 } 01107 } else { 01108 throw CanteraError(subname.c_str(), 01109 "Unspecified standardConc model"); 01110 } 01111 01112 bool m_ok = importPhase(phaseNode, this); 01113 if (!m_ok) { 01114 throw CanteraError(subname.c_str(),"importPhase failed "); 01115 } 01116 } 01117 01118 /* 01119 * Initialization of an IdealSolidSolnPhase phase using an 01120 * xml file 01121 * 01122 * This routine is a precursor to constructPhaseFile(XML_Node*) 01123 * routine, which does most of the work. 01124 * 01125 * @param infile XML file containing the description of the 01126 * phase 01127 * 01128 * @param id Optional parameter identifying the name of the 01129 * phase. If none is given, the first XML 01130 * phase element will be used. 01131 */ 01132 void IdealSolidSolnPhase:: 01133 constructPhaseFile(std::string inputFile, std::string id) { 01134 if (inputFile.size() == 0) { 01135 throw CanteraError("IdealSolidSolnPhase::constructPhaseFile", 01136 "input file is null"); 01137 } 01138 string path = findInputFile(inputFile); 01139 ifstream fin(path.c_str()); 01140 if (!fin) { 01141 throw CanteraError("IdealSolidSolnPhase::constructPhaseFile","could not open " 01142 +path+" for reading."); 01143 } 01144 /* 01145 * The phase object automatically constructs an XML object. 01146 * Use this object to store information. 01147 */ 01148 XML_Node &phaseNode_XML = xml(); 01149 XML_Node *fxml = new XML_Node(); 01150 fxml->build(fin); 01151 XML_Node *fxml_phase = findXMLPhase(fxml, id); 01152 if (!fxml_phase) { 01153 throw CanteraError("IdealSolidSolnPhase::constructPhaseFile", 01154 "ERROR: Can not find phase named " + 01155 id + " in file named " + inputFile); 01156 } 01157 fxml_phase->copy(&phaseNode_XML); 01158 01159 constructPhaseXML(*fxml_phase, id); 01160 delete fxml; 01161 } 01162 01163 /* 01164 * @internal 01165 * Import and initialize a ThermoPhase object 01166 * using an XML tree. 01167 * Here we read extra information about the XML description 01168 * of a phase. Regular information about elements and species 01169 * and their reference state thermodynamic information 01170 * have already been read at this point. 01171 * For example, we do not need to call this function for 01172 * ideal gas equations of state. 01173 * This function is called from importPhase() 01174 * after the elements and the 01175 * species are initialized with default ideal solution 01176 * level data. 01177 * 01178 * @param phaseNode This object must be the phase node of a 01179 * complete XML tree 01180 * description of the phase, including all of the 01181 * species data. In other words while "phase" must 01182 * point to an XML phase object, it must have 01183 * sibling nodes "speciesData" that describe 01184 * the species in the phase. 01185 * @param id ID of the phase. If nonnull, a check is done 01186 * to see if phaseNode is pointing to the phase 01187 * with the correct id. 01188 */ 01189 void IdealSolidSolnPhase::initThermoXML(XML_Node& phaseNode, std::string id) { 01190 string subname = "IdealSolidSolnPhase::initThermoXML"; 01191 /* 01192 * Check on the thermo field. Must have: 01193 * <thermo model="IdealSolidSolution" /> 01194 */ 01195 if (phaseNode.hasChild("thermo")) { 01196 XML_Node& thNode = phaseNode.child("thermo"); 01197 string mStringa = thNode.attrib("model"); 01198 string mString = lowercase(mStringa); 01199 if (mString != "idealsolidsolution") { 01200 throw CanteraError(subname.c_str(), 01201 "Unknown thermo model: " + mStringa); 01202 } 01203 } else { 01204 throw CanteraError(subname.c_str(), 01205 "Unspecified thermo model"); 01206 } 01207 01208 /* 01209 * Form of the standard concentrations. Must have one of: 01210 * 01211 * <standardConc model="unity" /> 01212 * <standardConc model="molar_volume" /> 01213 * <standardConc model="solvent_volume" /> 01214 */ 01215 if (phaseNode.hasChild("standardConc")) { 01216 XML_Node& scNode = phaseNode.child("standardConc"); 01217 string formStringa = scNode.attrib("model"); 01218 string formString = lowercase(formStringa); 01219 if (formString == "unity") { 01220 m_formGC = 0; 01221 } else if (formString == "molar_volume") { 01222 m_formGC = 1; 01223 } else if (formString == "solvent_volume") { 01224 m_formGC = 2; 01225 } else { 01226 throw CanteraError(subname.c_str(), 01227 "Unknown standardConc model: " + formStringa); 01228 } 01229 } else { 01230 throw CanteraError(subname.c_str(), 01231 "Unspecified standardConc model"); 01232 } 01233 01234 /* 01235 * Initialize all of the lengths now that we know how many species 01236 * there are in the phase. 01237 */ 01238 initLengths(); 01239 /* 01240 * Now go get the molar volumes 01241 */ 01242 XML_Node& speciesList = phaseNode.child("speciesArray"); 01243 XML_Node* speciesDB = get_XML_NameID("speciesData", speciesList["datasrc"], 01244 &phaseNode.root()); 01245 const vector<string>&sss = speciesNames(); 01246 01247 for (int k = 0; k < m_kk; k++) { 01248 XML_Node* s = speciesDB->findByAttr("name", sss[k]); 01249 XML_Node *ss = s->findByName("standardState"); 01250 m_speciesMolarVolume[k] = getFloat(*ss, "molarVolume", "toSI"); 01251 } 01252 01253 /* 01254 * Call the base initThermo, which handles setting the initial 01255 * state. 01256 */ 01257 ThermoPhase::initThermoXML(phaseNode, id); 01258 } 01259 01260 /* 01261 * This internal function adjusts the lengths of arrays 01262 */ 01263 void IdealSolidSolnPhase:: 01264 initLengths() { 01265 m_kk = nSpecies(); 01266 m_mm = nElements(); 01267 01268 /* 01269 * Obtain the limits of the temperature from the species 01270 * thermo handler's limits. 01271 */ 01272 doublereal tmin = m_spthermo->minTemp(); 01273 doublereal tmax = m_spthermo->maxTemp(); 01274 if (tmin > 0.0) m_tmin = tmin; 01275 if (tmax > 0.0) m_tmax = tmax; 01276 01277 /* 01278 * Obtain the reference pressure by calling the ThermoPhase 01279 * function refPressure, which in turm calls the 01280 * species thermo reference pressure function of the 01281 * same name. 01282 */ 01283 m_Pref = refPressure(); 01284 01285 int leng = m_kk; 01286 m_h0_RT.resize(leng); 01287 m_g0_RT.resize(leng); 01288 m_expg0_RT.resize(leng); 01289 m_cp0_R.resize(leng); 01290 m_s0_R.resize(leng); 01291 m_pe.resize(leng, 0.0); 01292 m_pp.resize(leng); 01293 m_speciesMolarVolume.resize(leng); 01294 } 01295 01296 /* 01297 * Set mixture to an equilibrium state consistent with specified 01298 * element potentials and temperature. 01299 * 01300 * @param lambda_RT vector of non-dimensional element potentials 01301 * \f$ \lambda_m/RT \f$. 01302 * 01303 */ 01304 void IdealSolidSolnPhase:: 01305 setToEquilState(const doublereal* lambda_RT) 01306 { 01307 const array_fp& grt = gibbs_RT_ref(); 01308 01309 // set the pressure and composition to be consistent with 01310 // the temperature, 01311 doublereal pres = 0.0; 01312 for (int k = 0; k < m_kk; k++) { 01313 m_pp[k] = -grt[k]; 01314 for (int m = 0; m < m_mm; m++) { 01315 m_pp[k] += nAtoms(k,m)*lambda_RT[m]; 01316 } 01317 m_pp[k] = m_Pref * exp(m_pp[k]); 01318 pres += m_pp[k]; 01319 } 01320 doublereal *dptr = DATA_PTR(m_pp); 01321 setState_PX(pres, dptr); 01322 } 01323 //================================================================================================ 01324 /* 01325 * 01326 * speciesMolarVolume() 01327 * 01328 * Report the molar volume of species k 01329 * 01330 * units - \f$ m^3 kmol^-1 \f$ 01331 */ 01332 double IdealSolidSolnPhase:: 01333 speciesMolarVolume(int k) const 01334 { 01335 return m_speciesMolarVolume[k]; 01336 } 01337 01338 /* 01339 * 01340 * getSpeciesMolarVolumes(): 01341 * 01342 * Fill in a return vector containing the species molar volumes 01343 * units - \f$ m^3 kmol^-1 \f$ 01344 */ 01345 void IdealSolidSolnPhase:: 01346 getSpeciesMolarVolumes(doublereal *smv) const 01347 { 01348 copy(m_speciesMolarVolume.begin(), m_speciesMolarVolume.end(), smv); 01349 } 01350 //================================================================================================ 01351 /* 01352 * 01353 * _updateThermo() 01354 * 01355 * This function gets called for every call to functions in this 01356 * class. It checks to see whether the temperature has changed and 01357 * thus the reference thermodynamics functions for all of the species 01358 * must be recalculated. 01359 * If the temperature has changed, the species thermo manager is called 01360 * to recalculate G, Cp, H, and S at the current temperature. 01361 */ 01362 void IdealSolidSolnPhase:: 01363 _updateThermo() const { 01364 doublereal tnow = temperature(); 01365 if (m_tlast != tnow) { 01366 /* 01367 * Update the thermodynamic functions of the reference state. 01368 */ 01369 m_spthermo->update(tnow, DATA_PTR(m_cp0_R), DATA_PTR(m_h0_RT), 01370 DATA_PTR(m_s0_R)); 01371 m_tlast = tnow; 01372 doublereal rrt = 1.0 / (GasConstant * tnow); 01373 int k; 01374 doublereal deltaE; 01375 for (k = 0; k < m_kk; k++) { 01376 deltaE = rrt * m_pe[k]; 01377 m_h0_RT[k] += deltaE; 01378 m_g0_RT[k] = m_h0_RT[k] - m_s0_R[k]; 01379 } 01380 m_tlast = tnow; 01381 } 01382 } 01383 //================================================================================================ 01384 } // end namespace Cantera 01385 //==================================================================================================