00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef CT_NASATHERMO_H
00017 #define CT_NASATHERMO_H
00018 #include <string>
00019
00020 #include "SpeciesThermoMgr.h"
00021 #include "NasaPoly1.h"
00022 #include "speciesThermoTypes.h"
00023
00024 #include "global.h"
00025
00026 namespace Cantera {
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 class NasaThermo : public SpeciesThermo {
00056
00057 public:
00058
00059
00060
00061
00062
00063 const int ID;
00064
00065
00066 NasaThermo() :
00067 ID(NASA),
00068 m_tlow_max(0.0),
00069 m_thigh_min(1.e30),
00070 m_p0(-1.0),
00071 m_ngroups(0)
00072 {
00073 m_t.resize(6);
00074 }
00075
00076
00077
00078
00079
00080 NasaThermo(const NasaThermo &right) :
00081 ID(NASA),
00082 m_tlow_max(0.0),
00083 m_thigh_min(1.e30),
00084 m_p0(-1.0),
00085 m_ngroups(0)
00086 {
00087 *this = operator=(right);
00088 }
00089
00090
00091
00092
00093
00094 NasaThermo& operator=(const NasaThermo &right) {
00095
00096
00097
00098 if (this == &right) return *this;
00099
00100 m_high = right.m_high;
00101 m_low = right.m_low;
00102 m_index = right.m_index;
00103 m_tmid = right.m_tmid;
00104 m_tlow_max = right.m_tlow_max;
00105 m_thigh_min = right.m_thigh_min;
00106 m_tlow = right.m_tlow;
00107 m_thigh = right.m_thigh;
00108 m_p0 = right.m_p0;
00109 m_ngroups = right.m_ngroups;
00110 m_t = right.m_t;
00111 m_group_map = right.m_group_map;
00112 m_posInGroup_map = right.m_posInGroup_map;
00113 m_name = right.m_name;
00114
00115 return *this;
00116 }
00117
00118
00119
00120 virtual ~NasaThermo() {}
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 virtual SpeciesThermo *duplMyselfAsSpeciesThermo() const {
00132 NasaThermo *nt = new NasaThermo(*this);
00133 return (SpeciesThermo *) nt;
00134 }
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 virtual void install(string name, int index, int type,
00159 const doublereal* c,
00160 doublereal minTemp, doublereal maxTemp,
00161 doublereal refPressure) {
00162
00163 m_name[index] = name;
00164 int imid = int(c[0]);
00165 int igrp = m_index[imid];
00166 if (igrp == 0) {
00167 vector<NasaPoly1> v;
00168 m_high.push_back(v);
00169 m_low.push_back(v);
00170 m_tmid.push_back(c[0]);
00171 m_index[imid] = igrp = static_cast<int>(m_high.size());
00172 m_ngroups++;
00173 }
00174
00175 m_group_map[index] = igrp;
00176 m_posInGroup_map[index] = (int) m_low[igrp-1].size();
00177
00178 doublereal tlow = minTemp;
00179 doublereal tmid = c[0];
00180 doublereal thigh = maxTemp;
00181 const doublereal* clow = c + 1;
00182
00183 vector_fp chigh(7);
00184 copy(c + 8, c + 15, chigh.begin());
00185
00186 m_high[igrp-1].push_back(NasaPoly1(index, tmid, thigh,
00187 refPressure, &chigh[0]));
00188 m_low[igrp-1].push_back(NasaPoly1(index, tlow, tmid,
00189 refPressure, clow));
00190
00191 vector_fp clu(7), chu(7);
00192 clu[5] = clow[0];
00193 clu[6] = clow[1];
00194 copy(clow+2, clow+7, clu.begin());
00195 chu[5] = chigh[0];
00196 chu[6] = chigh[1];
00197 copy(chigh.begin()+2, chigh.begin()+7, chu.begin());
00198
00199 checkContinuity(name, tmid, &clu[0], &chu[0]);
00200
00201 if (tlow > m_tlow_max) m_tlow_max = tlow;
00202 if (thigh < m_thigh_min) m_thigh_min = thigh;
00203 if ((int) m_tlow.size() < index + 1) {
00204 m_tlow.resize(index + 1, tlow);
00205 m_thigh.resize(index + 1, thigh);
00206 }
00207 m_tlow[index] = tlow;
00208 m_thigh[index] = thigh;
00209 if (m_p0 < 0.0) {
00210 m_p0 = refPressure;
00211 } else if (fabs(m_p0 - refPressure) > 0.1) {
00212 string logmsg = " WARNING NasaThermo: New Species, " + name + ", has a different reference pressure, "
00213 + fp2str(refPressure) + ", than existing reference pressure, " + fp2str(m_p0) + "\n";
00214 writelog(logmsg);
00215 logmsg = " This may become a fatal error in the future \n";
00216 writelog(logmsg);
00217 }
00218 m_p0 = refPressure;
00219 }
00220
00221
00222
00223
00224
00225
00226
00227 virtual void install_STIT(SpeciesThermoInterpType *stit_ptr) {
00228 throw CanteraError("install_STIT", "not implemented");
00229 }
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 virtual void update_one(int k, doublereal t, doublereal* cp_R,
00245 doublereal* h_RT, doublereal* s_R) const {
00246
00247 m_t[0] = t;
00248 m_t[1] = t*t;
00249 m_t[2] = m_t[1]*t;
00250 m_t[3] = m_t[2]*t;
00251 m_t[4] = 1.0/t;
00252 m_t[5] = log(t);
00253
00254 int grp = m_group_map[k];
00255 int pos = m_posInGroup_map[k];
00256 const vector<NasaPoly1> &mlg = m_low[grp-1];
00257 const NasaPoly1 *nlow = &(mlg[pos]);
00258
00259 doublereal tmid = nlow->maxTemp();
00260 if (t < tmid) {
00261 nlow->updateProperties(&m_t[0], cp_R, h_RT, s_R);
00262 } else {
00263 const vector<NasaPoly1> &mhg = m_high[grp-1];
00264 const NasaPoly1 *nhigh = &(mhg[pos]);
00265 nhigh->updateProperties(&m_t[0], cp_R, h_RT, s_R);
00266 }
00267 }
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284 virtual void update(doublereal t, doublereal* cp_R,
00285 doublereal* h_RT, doublereal* s_R) const {
00286 int i;
00287
00288
00289 m_t[0] = t;
00290 m_t[1] = t*t;
00291 m_t[2] = m_t[1]*t;
00292 m_t[3] = m_t[2]*t;
00293 m_t[4] = 1.0/t;
00294 m_t[5] = log(t);
00295
00296
00297 vector<NasaPoly1>::const_iterator _begin, _end;
00298 for (i = 0; i != m_ngroups; i++) {
00299 if (t > m_tmid[i]) {
00300 _begin = m_high[i].begin();
00301 _end = m_high[i].end();
00302 }
00303 else {
00304 _begin = m_low[i].begin();
00305 _end = m_low[i].end();
00306 }
00307 for (; _begin != _end; ++_begin)
00308 _begin->updateProperties(&m_t[0], cp_R, h_RT, s_R);
00309 }
00310 }
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 virtual doublereal minTemp(int k=-1) const {
00323 if (k < 0)
00324 return m_tlow_max;
00325 else
00326 return m_tlow[k];
00327 }
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 virtual doublereal maxTemp(int k=-1) const {
00340 if (k < 0)
00341 return m_thigh_min;
00342 else
00343 return m_thigh[k];
00344 }
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359 virtual doublereal refPressure(int k = -1) const {
00360 return m_p0;
00361 }
00362
00363
00364
00365
00366
00367
00368
00369 virtual int reportType(int index) const { return NASA; }
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385 virtual void reportParams(int index, int &type,
00386 doublereal * const c,
00387 doublereal &minTemp,
00388 doublereal &maxTemp,
00389 doublereal &refPressure) const {
00390 type = reportType(index);
00391 if (type == NASA) {
00392 int grp = m_group_map[index];
00393 int pos = m_posInGroup_map[index];
00394 const vector<NasaPoly1> &mlg = m_low[grp-1];
00395 const vector<NasaPoly1> &mhg = m_high[grp-1];
00396 const NasaPoly1 *lowPoly = &(mlg[pos]);
00397 const NasaPoly1 *highPoly = &(mhg[pos]);
00398 int itype = NASA;
00399 doublereal tmid = lowPoly->maxTemp();
00400 c[0] = tmid;
00401 int n;
00402 double ttemp;
00403 lowPoly->reportParameters(n, itype, minTemp, ttemp, refPressure,
00404 c + 1);
00405 if (n != index) {
00406 throw CanteraError(" ", "confused");
00407 }
00408 if (itype != NASA1) {
00409 throw CanteraError(" ", "confused");
00410 }
00411 highPoly->reportParameters(n, itype, ttemp, maxTemp, refPressure,
00412 c + 8);
00413 if (n != index) {
00414 throw CanteraError(" ", "confused");
00415 }
00416 if (itype != NASA1) {
00417 throw CanteraError(" ", "confused");
00418 }
00419 } else {
00420 throw CanteraError(" ", "confused");
00421 }
00422 }
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437 virtual void modifyParams(int index, doublereal *c) {
00438 int type = reportType(index);
00439 if (type == NASA) {
00440 int grp = m_group_map[index];
00441 int pos = m_posInGroup_map[index];
00442 vector<NasaPoly1> &mlg = m_low[grp-1];
00443 vector<NasaPoly1> &mhg = m_high[grp-1];
00444 NasaPoly1 *lowPoly = &(mlg[pos]);
00445 NasaPoly1 *highPoly = &(mhg[pos]);
00446 doublereal tmid = lowPoly->maxTemp();
00447 if (c[0] != tmid) {
00448 throw CanteraError(" ", "Tmid cannot be changed");
00449 }
00450 lowPoly->modifyParameters(c + 1);
00451 highPoly->modifyParameters(c + 8);
00452 checkContinuity(m_name[index], c[0], c + 1, c + 8);
00453 } else {
00454 throw CanteraError(" ", "confused");
00455 }
00456 }
00457
00458 #ifdef H298MODIFY_CAPABILITY
00459 virtual doublereal reportOneHf298(const int k) const {
00460
00461 int grp = m_group_map[k];
00462 int pos = m_posInGroup_map[k];
00463 const vector<NasaPoly1> &mlg = m_low[grp-1];
00464 const NasaPoly1 *nlow = &(mlg[pos]);
00465 doublereal tmid = nlow->maxTemp();
00466 double h;
00467 if (298.15 <= tmid) {
00468 h = nlow->reportHf298(0);
00469 } else {
00470 const vector<NasaPoly1> &mhg = m_high[grp-1];
00471 const NasaPoly1 *nhigh = &(mhg[pos]);
00472 h = nhigh->reportHf298(0);
00473 }
00474 return h;
00475 }
00476
00477 virtual void modifyOneHf298(const int k, const doublereal Hf298New) {
00478 int grp = m_group_map[k];
00479 int pos = m_posInGroup_map[k];
00480 vector<NasaPoly1> &mlg = m_low[grp-1];
00481 NasaPoly1 *nlow = &(mlg[pos]);
00482 vector<NasaPoly1> &mhg = m_high[grp-1];
00483 NasaPoly1 *nhigh = &(mhg[pos]);
00484 doublereal tmid = nlow->maxTemp();
00485
00486 double hnow = reportOneHf298(k);
00487 double delH = Hf298New - hnow;
00488 if (298.15 <= tmid) {
00489 nlow->modifyOneHf298(k, Hf298New);
00490 double h = nhigh->reportHf298(0);
00491 double hnew = h + delH;
00492 nhigh->modifyOneHf298(k, hnew);
00493 } else {
00494 nhigh->modifyOneHf298(k, Hf298New);
00495 double h = nlow->reportHf298(0);
00496 double hnew = h + delH;
00497 nlow->modifyOneHf298(k, hnew);
00498 }
00499
00500 }
00501 #endif
00502
00503 protected:
00504
00505
00506
00507
00508
00509
00510
00511 vector<vector<NasaPoly1> > m_high;
00512
00513
00514
00515
00516
00517
00518
00519
00520 vector<vector<NasaPoly1> > m_low;
00521
00522
00523
00524
00525
00526 map<int, int> m_index;
00527
00528
00529
00530
00531
00532 vector_fp m_tmid;
00533
00534
00535 doublereal m_tlow_max;
00536
00537
00538 doublereal m_thigh_min;
00539
00540
00541
00542
00543
00544 vector_fp m_tlow;
00545
00546
00547
00548
00549
00550 vector_fp m_thigh;
00551
00552
00553
00554
00555
00556 doublereal m_p0;
00557
00558
00559 int m_ngroups;
00560
00561
00562 mutable vector_fp m_t;
00563
00564
00565
00566
00567
00568
00569
00570 mutable map<int, int> m_group_map;
00571
00572
00573
00574
00575
00576
00577 mutable map<int, int> m_posInGroup_map;
00578
00579
00580 mutable map<int, string> m_name;
00581
00582 private:
00583
00584
00585
00586
00587
00588
00589
00590
00591 void checkContinuity(std::string name, double tmid, const doublereal* clow,
00592 doublereal* chigh);
00593
00594
00595
00596
00597
00598
00599 doublereal enthalpy_RT(double t, const doublereal* c) {
00600 return c[0] + 0.5*c[1]*t + OneThird*c[2]*t*t
00601 + 0.25*c[3]*t*t*t + 0.2*c[4]*t*t*t*t
00602 + c[5]/t;
00603 }
00604
00605
00606
00607
00608
00609
00610 doublereal entropy_R(double t, const doublereal* c) {
00611 return c[0]*log(t) + c[1]*t + 0.5*c[2]*t*t
00612 + OneThird*c[3]*t*t*t + 0.25*c[4]*t*t*t*t
00613 + c[6];
00614 }
00615
00616
00617
00618 };
00619
00620 }
00621
00622 #endif
00623