00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "Mu0Poly.h"
00016 #include "ctexceptions.h"
00017 #include "speciesThermoTypes.h"
00018 #include "SpeciesThermo.h"
00019 #include "xml.h"
00020 #include "ctml.h"
00021
00022 using namespace std;
00023 using namespace ctml;
00024
00025 namespace Cantera {
00026
00027
00028 Mu0Poly::Mu0Poly() : m_numIntervals(0),
00029 m_H298(0.0),
00030 m_lowT(0.0),
00031 m_highT(0.0),
00032 m_Pref(0.0),
00033 m_index(0) {
00034 }
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 Mu0Poly::Mu0Poly(int n, doublereal tlow, doublereal thigh,
00054 doublereal pref,
00055 const doublereal* coeffs) :
00056 m_numIntervals(0),
00057 m_H298(0.0),
00058 m_lowT (tlow),
00059 m_highT (thigh),
00060 m_Pref (pref),
00061 m_index (n) {
00062
00063 processCoeffs(coeffs);
00064 }
00065
00066
00067 Mu0Poly::Mu0Poly(const Mu0Poly &b)
00068 : m_numIntervals (b.m_numIntervals),
00069 m_H298 (b.m_H298),
00070 m_t0_int (b.m_t0_int),
00071 m_mu0_R_int (b.m_mu0_R_int),
00072 m_h0_R_int (b.m_h0_R_int),
00073 m_s0_R_int (b.m_s0_R_int),
00074 m_cp0_R_int (b.m_cp0_R_int),
00075 m_lowT (b.m_lowT),
00076 m_highT (b.m_highT),
00077 m_Pref (b.m_Pref),
00078 m_index (b.m_index) {
00079 }
00080
00081 Mu0Poly& Mu0Poly::operator=(const Mu0Poly& b) {
00082 if (&b != this) {
00083 m_numIntervals = b.m_numIntervals;
00084 m_H298 = b.m_H298;
00085 m_t0_int = b.m_t0_int;
00086 m_mu0_R_int = b.m_mu0_R_int;
00087 m_h0_R_int = b.m_h0_R_int;
00088 m_s0_R_int = b.m_s0_R_int;
00089 m_cp0_R_int = b.m_cp0_R_int;
00090 m_lowT = b.m_lowT;
00091 m_highT = b.m_highT;
00092 m_Pref = b.m_Pref;
00093 m_index = b.m_index;
00094 }
00095 return *this;
00096 }
00097
00098
00099
00100
00101 Mu0Poly::~Mu0Poly(){
00102 }
00103
00104 SpeciesThermoInterpType *
00105 Mu0Poly::duplMyselfAsSpeciesThermoInterpType() const {
00106 Mu0Poly* mp = new Mu0Poly(*this);
00107 return (SpeciesThermoInterpType *) mp;
00108 }
00109
00110 doublereal Mu0Poly::minTemp() const { return m_lowT;}
00111 doublereal Mu0Poly::maxTemp() const { return m_highT;}
00112 doublereal Mu0Poly::refPressure() const { return m_Pref; }
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 void Mu0Poly::
00129 updateProperties(const doublereal* tt, doublereal* cp_R,
00130 doublereal* h_RT, doublereal* s_R) const {
00131 int j = m_numIntervals;
00132 double T = *tt;
00133 for (int i = 0; i < m_numIntervals; i++) {
00134 double T2 = m_t0_int[i+1];
00135 if (T <=T2) {
00136 j = i;
00137 break;
00138 }
00139 }
00140 double T1 = m_t0_int[j];
00141 double cp_Rj = m_cp0_R_int[j];
00142
00143 doublereal rt = 1.0/T;
00144 cp_R[m_index] = cp_Rj;
00145 h_RT[m_index] = rt*(m_h0_R_int[j] + (T - T1) * cp_Rj);
00146 s_R[m_index] = m_s0_R_int[j] + cp_Rj * (log(T/T1));
00147 }
00148
00149 void Mu0Poly::
00150 updatePropertiesTemp(const doublereal T,
00151 doublereal* cp_R,
00152 doublereal* h_RT,
00153 doublereal* s_R) const {
00154 updateProperties(&T, cp_R, h_RT, s_R);
00155 }
00156
00157
00158
00159
00160
00161
00162
00163 void Mu0Poly::reportParameters(int &n, int &type,
00164 doublereal &tlow, doublereal &thigh,
00165 doublereal &pref,
00166 doublereal* const coeffs) const {
00167 n = m_index;
00168 type = MU0_INTERP;
00169 tlow = m_lowT;
00170 thigh = m_highT;
00171 pref = m_Pref;
00172 coeffs[0] = m_numIntervals+1;
00173 coeffs[1] = m_H298 * GasConstant;
00174 int j = 2;
00175 for (int i = 0; i < m_numIntervals+1; i++) {
00176 coeffs[j] = m_t0_int[i];
00177 coeffs[j+1] = m_mu0_R_int[i] * GasConstant;
00178 j += 2;
00179 }
00180 }
00181
00182 void Mu0Poly::modifyParameters(doublereal* coeffs) {
00183 processCoeffs(coeffs);
00184 }
00185
00186
00187
00188
00189
00190
00191 void installMu0ThermoFromXML(std::string speciesName,
00192 SpeciesThermo& sp, int k,
00193 const XML_Node* Mu0Node_ptr) {
00194
00195 doublereal tmin, tmax;
00196 bool dimensionlessMu0Values = false;
00197 const XML_Node& Mu0Node = *Mu0Node_ptr;
00198
00199 tmin = fpValue(Mu0Node["Tmin"]);
00200 tmax = fpValue(Mu0Node["Tmax"]);
00201 doublereal pref = fpValue(Mu0Node["Pref"]);
00202
00203 doublereal h298 = 0.0;
00204 if (Mu0Node.hasChild("H298")) {
00205 h298 = getFloat(Mu0Node, "H298", "actEnergy");
00206 }
00207
00208 int numPoints = 1;
00209 if (Mu0Node.hasChild("numPoints")) {
00210 numPoints = getInteger(Mu0Node, "numPoints");
00211 }
00212
00213 vector_fp cValues(numPoints);
00214 const XML_Node *valNode_ptr =
00215 getByTitle(const_cast<XML_Node&>(Mu0Node), "Mu0Values");
00216 if (!valNode_ptr) {
00217 throw CanteraError("installMu0ThermoFromXML",
00218 "missing required while processing "
00219 + speciesName);
00220 }
00221 getFloatArray(*valNode_ptr, cValues, true, "actEnergy");
00222
00223
00224
00225
00226
00227 string uuu = (*valNode_ptr)["units"];
00228 if (uuu == "Dimensionless") {
00229 dimensionlessMu0Values = true;
00230 }
00231 int ns = cValues.size();
00232 if (ns != numPoints) {
00233 throw CanteraError("installMu0ThermoFromXML",
00234 "numPoints inconsistent while processing "
00235 + speciesName);
00236 }
00237
00238 vector_fp cTemperatures(numPoints);
00239 const XML_Node *tempNode_ptr =
00240 getByTitle(const_cast<XML_Node&>(Mu0Node), "Mu0Temperatures");
00241 if (!tempNode_ptr) {
00242 throw CanteraError("installMu0ThermoFromXML",
00243 "missing required while processing + "
00244 + speciesName);
00245 }
00246 getFloatArray(*tempNode_ptr, cTemperatures, false);
00247 ns = cTemperatures.size();
00248 if (ns != numPoints) {
00249 throw CanteraError("installMu0ThermoFromXML",
00250 "numPoints inconsistent while processing "
00251 + speciesName);
00252 }
00253
00254
00255
00256
00257 if (dimensionlessMu0Values) {
00258 for (int i = 0; i < numPoints; i++) {
00259 cValues[i] *= cTemperatures[i] / 273.15;
00260 }
00261 }
00262
00263
00264 vector_fp c(2 + 2 * numPoints);
00265
00266 c[0] = numPoints;
00267 c[1] = h298;
00268 for (int i = 0; i < numPoints; i++) {
00269 c[2+i*2] = cTemperatures[i];
00270 c[2+i*2+1] = cValues[i];
00271 }
00272
00273 sp.install(speciesName, k, MU0_INTERP, &c[0], tmin, tmax, pref);
00274 }
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 void Mu0Poly::processCoeffs(const doublereal* coeffs) {
00294
00295 int i, iindex;
00296 double T1, T2;
00297 int nPoints = (int) coeffs[0];
00298 if (nPoints < 2) {
00299 throw CanteraError("Mu0Poly",
00300 "nPoints must be >= 2");
00301 }
00302 m_numIntervals = nPoints - 1;
00303 m_H298 = coeffs[1] / GasConstant;
00304 int iT298 = 0;
00305
00306
00307
00308 m_t0_int.resize(nPoints);
00309 m_h0_R_int.resize(nPoints);
00310 m_s0_R_int.resize(nPoints);
00311 m_cp0_R_int.resize(nPoints);
00312 m_mu0_R_int.resize(nPoints);
00313
00314
00315
00316
00317
00318 bool ifound = false;
00319 for (i = 0, iindex = 2; i < nPoints; i++) {
00320 T1 = coeffs[iindex];
00321 m_t0_int[i] = T1;
00322 m_mu0_R_int[i] = coeffs[iindex+1] / GasConstant;
00323 if (T1 == 298.15) {
00324 iT298 = i;
00325 ifound = true;
00326 }
00327 if (i < nPoints - 1) {
00328 T2 = coeffs[iindex+2];
00329 if (T2 <= T1) {
00330 throw CanteraError("Mu0Poly",
00331 "Temperatures are not monotonic increasing");
00332 }
00333 }
00334 iindex += 2;
00335 }
00336 if (!ifound) {
00337 throw CanteraError("Mu0Poly",
00338 "One temperature has to be 298.15");
00339 }
00340
00341
00342
00343
00344 doublereal mu2, s1, s2, h1, h2, cpi, deltaMu, deltaT;
00345 T1 = m_t0_int[iT298];
00346 doublereal mu1 = m_mu0_R_int[iT298];
00347 m_h0_R_int[iT298] = m_H298;
00348 m_s0_R_int[iT298] = - (mu1 - m_h0_R_int[iT298]) / T1;
00349 for (i = iT298; i < m_numIntervals; i++) {
00350 T1 = m_t0_int[i];
00351 s1 = m_s0_R_int[i];
00352 h1 = m_h0_R_int[i];
00353 mu1 = m_mu0_R_int[i];
00354 T2 = m_t0_int[i+1];
00355 mu2 = m_mu0_R_int[i+1];
00356 deltaMu = mu2 - mu1;
00357 deltaT = T2 - T1;
00358 cpi = (deltaMu - T1 * s1 + T2 * s1) / (deltaT - T2 * log(T2/T1));
00359 h2 = h1 + cpi * deltaT;
00360 s2 = s1 + cpi * log(T2/T1);
00361 m_cp0_R_int[i] = cpi;
00362 m_h0_R_int[i+1] = h2;
00363 m_s0_R_int[i+1] = s2;
00364 m_cp0_R_int[i+1] = cpi;
00365 }
00366
00367
00368
00369
00370 if (iT298 > 0) {
00371 T2 = m_t0_int[iT298];
00372 mu2 = m_mu0_R_int[iT298];
00373 m_h0_R_int[iT298] = m_H298;
00374 m_s0_R_int[iT298] = - (mu2 - m_h0_R_int[iT298]) / T2;
00375 for (i = iT298 - 1; i >= 0; i--) {
00376 T1 = m_t0_int[i];
00377 mu1 = m_mu0_R_int[i];
00378 T2 = m_t0_int[i+1];
00379 mu2 = m_mu0_R_int[i+1];
00380 s2 = m_s0_R_int[i+1];
00381 h2 = m_h0_R_int[i+1];
00382 deltaMu = mu2 - mu1;
00383 deltaT = T2 - T1;
00384 cpi = (deltaMu - T1 * s2 + T2 * s2) / (deltaT - T1 * log(T2/T1));
00385 h1 = h2 - cpi * deltaT;
00386 s1 = s2 - cpi * log(T2/T1);
00387 m_cp0_R_int[i] = cpi;
00388 m_h0_R_int[i] = h1;
00389 m_s0_R_int[i] = s1;
00390 if (i == (m_numIntervals-1)) {
00391 m_cp0_R_int[i+1] = cpi;
00392 }
00393 }
00394 }
00395 #ifdef DEBUG_HKM_NOT
00396 printf(" Temp mu0(J/kmol) cp0(J/kmol/K) "
00397 " h0(J/kmol) s0(J/kmol/K) \n");
00398 for (i = 0; i < nPoints; i++) {
00399 printf("%12.3g %12.5g %12.5g %12.5g %12.5g\n",
00400 m_t0_int[i], m_mu0_R_int[i] * GasConstant,
00401 m_cp0_R_int[i]* GasConstant,
00402 m_h0_R_int[i]* GasConstant,
00403 m_s0_R_int[i]* GasConstant);
00404 fflush(stdout);
00405 }
00406 #endif
00407 }
00408
00409 }
00410
00411
00412
00413
00414