26 static string int2s(
int n, std::string fmt=
"%d")
29 sprintf(buf, fmt.c_str(), n);
34 CK_SyntaxError::CK_SyntaxError(std::ostream& f,
35 const std::string& s,
int linenum)
38 m_msg +=
"Syntax error: " + s;
40 m_msg +=
" (line " + int2s(linenum) +
")\n";
45 static int parseGroupString(std::string str, std::vector<std::string>& esyms,
53 char n,
int linenum = -1)
56 "contain an integer", linenum);
64 std::string s,
int linenum = -1)
66 string msg =
"illegal number: "+s;
73 static string d2e(
string s)
79 for (n = 0; n < sz; n++) {
83 }
else if (ch ==
'd') {
90 static double de_atof(std::string s)
94 double rval = atof(r.c_str());
108 for (i = 1; i < (int) temp.size(); i++) {
109 double tlow = temp[i-1];
110 double thigh = temp[i];
112 string sss =
"error reading temperature";
119 static double getNumberFromString(std::string s)
123 int sz =
static_cast<int>(s.size());
125 for (
int n = 0; n < sz; n++) {
127 if (!inexp && (ch ==
'E' || ch ==
'e' || ch ==
'D' || ch ==
'd')) {
129 }
else if (ch ==
'+' || ch ==
'-') {
130 if (n > 0 && (s[n-1] !=
'E' && s[n-1]
131 !=
'e' && s[n-1] !=
'd' && s[n-1] !=
'D')) {
134 }
else if (ch !=
'.' && (ch < '0' || ch >
'9')) {
150 Species& sp, std::ostream& log)
158 sp.
comp[symbol] = atoms;
173 double tmid,
double tmax)
175 if (tmin == 0.0 || tmid == 0.0 || tmax == 0.0) {
177 "error reading Tmin, Tmid, or Tmax");
181 static void getSpecies(std::string s,
182 int n, vector<RxnSpecies>& species,
bool debug,
192 for (
int i = n-1; i >= 0; i--) {
193 if (!inplus && s[i] ==
'+') {
196 }
else if (inplus && s[i] !=
'+') {
200 pluses.push_back(-1);
201 size_t np = pluses.size();
203 for (
size_t nn = 0; nn < np; nn++) {
211 sp.push_back(s.substr(loc+1,nxt-loc-1));
215 size_t sz, j, strt=0;
217 for (
size_t nn = 0; nn < sp.size(); nn++) {
220 for (j = 0; j < sz; j++) {
221 if (!((r[j] >=
'0' && r[j] <=
'9') || r[j] ==
'.')) {
226 ss.name = r.substr(strt,sz);
230 ss.number = atof(r.substr(0,strt).c_str());
232 species.push_back(ss);
234 log << ss.number <<
" " << ss.name << endl;
247 std::string::const_iterator end, std::vector<std::string>& esyms,
248 std::vector<grouplist_t>& rxngroups)
250 bool ingroup =
false;
256 for (; begin != end; ++begin) {
260 }
else if (*begin ==
')') {
263 if (parseGroupString(g, esyms, igrp) >= 0) {
264 groups.push_back(igrp);
268 }
else if (*begin ==
'+') {
269 rxngroups.push_back(groups);
271 }
else if (ingroup && *begin !=
' ') {
275 rxngroups.push_back(groups);
283 CKParser::CKParser(std::istream* infile,
const std::string& fname,
292 m_ckfilename = fname;
316 const char commentChar =
'!';
319 const char undoCommentChar =
'%';
322 const char char13 = char(13);
325 const char char10 = char(10);
332 if (!m_buf.empty()) {
361 if (ch == char13 || (ch == char10 && (m_last_eol != char13))) {
370 string::size_type icom = line.find(commentChar);
373 if (icom == 0 && line.size() > 1 && line[1] == undoCommentChar) {
376 icom = line.find(commentChar);
378 int len =
static_cast<int>(line.size());
380 for (
int i = 0; i < len; i++)
if (!isprint(line[i])) {
384 s = line.substr(0, icom);
385 comment = line.substr(icom+1,len-icom-1);
413 bool CKParser::advanceToKeyword(
const std::string& kw,
const std::string& stop)
418 if (
match(s,
"<EOF>")) {
425 }
while (!
match(s,stop));
445 map<string,double> defaultWeights;
456 if (advanceToKeyword(
"ELEM",
"SPEC")) {
461 getTokens(s, static_cast<int>(s.size()), toks);
462 ntok =
static_cast<int>(toks.size());
465 if (firsttok == 0 &&
isKeyword(toks[0])) {
469 for (
int i = firsttok; i < ntok; i++) {
470 if (
match(toks[i],
"END")) {
476 el.
index =
static_cast<int>(elements.size());
489 if (find(elements.begin(),
490 elements.end(), el) < elements.end()) {
492 *
m_log <<
"warning... duplicate element "
493 << el.
name <<
" (ignored)." << endl;
495 elements.push_back(el);
502 if (elements.size() == 0) {
503 *
m_log <<
"no elements found." << endl;
506 return valid(elements);
533 if (advanceToKeyword(
"SPEC",
"THER")) {
538 getTokens(s, static_cast<int>(s.size()), toks);
539 ntok =
static_cast<int>(toks.size());
542 if (firsttok == 0 &&
isKeyword(toks[0])) {
546 for (
int i = firsttok; i < ntok; i++) {
547 if (
match(toks[i],
"END")) {
552 if (find(species.begin(), species.end(), sp)
555 *
m_log <<
"warning... duplicate species "
556 << sp.
name <<
" (ignored)." << endl;
560 species.push_back(sp);
567 if (species.size() == 0) {
590 int& optionFlag, std::ostream& log)
595 double tmin = -1.0, tmid = -1.0, tmax = -1.0;
596 if (temp.size() == 3) {
602 int nsp =
static_cast<int>(names.size());
610 if (
match(s,
"<EOF>")) {
613 if (
match(s,
"REAC")) {
617 }
while (!
match(s,
"THER"));
620 getTokens(s, static_cast<int>(s.size()), toks);
622 if (toks.size() >= 2) {
624 for (itt = 1; itt < toks.size(); itt++) {
625 if (
match(toks[itt],
"ALL")) {
627 }
else if (
match(toks[itt],
"NO_TMID")) {
629 log <<
"\nOption 'NO_TMID' specified. Default "
630 "midpoint temperature\n";
631 log <<
"will be used for all species.\n\n";
632 }
else if (
match(toks[itt],
"NASA9")) {
634 log <<
"Option NASA9 specified: Use new "
635 "nasa input file format\n\n";
636 }
else if (
match(toks[itt],
"NASA")) {
638 log <<
"Option NASA specified: Use old "
639 "nasa input file format\n\n";
641 "unrecognized THERMO option.",
m_line);
651 getTokens(s, static_cast<int>(s.size()), toks);
658 size_t nreg = toks.size() - 2;
661 for (
size_t i = 0; i <= nreg; i++) {
662 temp[i] = de_atof(toks[i]);
664 string defaultDate = toks[nreg+1];
669 log.flags(ios::showpoint | ios::fixed);
671 log << endl <<
" Default # of temperature regions: "
674 for (
size_t i = 0; i <= nreg; i++) {
675 log << temp[i] <<
" ";
686 if (toks.size() >= 3) {
687 tmin = de_atof(toks[0]);
688 tmid = de_atof(toks[1]);
689 tmax = de_atof(toks[2]);
693 log.flags(ios::showpoint | ios::fixed);
695 log << endl <<
" default Tlow, Tmid, Thigh: " << tmin <<
" "
696 << tmid <<
" " << tmax << endl;
700 temp.push_back(tmin);
701 temp.push_back(tmid);
702 temp.push_back(tmax);
714 "In NASA parser. However, we expect a NASA9 file format",
722 bool getAllSpecies = (nsp > 0 &&
match(names[0],
"<ALL>"));
727 map<string, int> dup;
734 already_read =
false;
739 if (spec.
name ==
"<END>") {
744 if (dup[spec.
name] == 2) {
745 log <<
"Warning: more than one THERMO record for "
746 <<
"species " << spec.
name << endl;
747 log <<
"Record at line " <<
m_line
748 <<
" of " << m_ckfilename <<
" ignored." << endl;
753 if (!already_read && (getAllSpecies
754 || (find(names.begin(), names.end(), spec.
name)
757 if (spec.
tmid == 0.0) {
759 log <<
"Warning: default Tmid used for species "
760 << spec.
name << endl;
761 if (spec.
tmid < 0.0) {
762 log <<
"Error: no default Tmid has been entered!"
766 species[spec.
name] = spec;
769 log << endl <<
"found species " << spec.
name;
770 log <<
" at line " <<
m_line
771 <<
" of " << m_ckfilename;
776 names.push_back(spec.
name);
777 nsp =
static_cast<int>(names.size());
809 }
while ((s.size() < 80) || (s[79] !=
'1'));
821 string nameid = s.substr(0,24);
823 getTokens(nameid, static_cast<int>(nameid.size()), toks);
827 for (j = 1; j < toks.size(); j++) {
839 for (i = 0; i < 4; i++) {
842 if (s[iloc] !=
' ') {
843 if (s[iloc+1] !=
' ') {
844 elementSym = s.substr(iloc,2);
846 elementSym = s.substr(iloc,1);
848 }
else if (s[iloc+1] !=
' ') {
849 elementSym = s.substr(iloc+1,1);
851 atoms = de_atof(s.substr(iloc+2,3));
859 sp.
tlow = de_atof(s.substr(45,10));
860 sp.
thigh = de_atof(s.substr(55,10));
863 sp.
tmid = de_atof(s.substr(65,8));
873 atoms = de_atof(s.substr(75,3));
879 while (loc < (
int)(s.size()-9)) {
882 elementSym += s[loc];
884 if (s[loc+1] !=
' ') {
885 elementSym += s[loc+1];
887 atoms = de_atof(s.substr(loc+2,8));
899 for (i = 0; i < 5; i++) {
900 numstr = s.substr(i*15, 15);
901 cf = getNumberFromString(numstr);
914 for (i = 0; i < 2; i++) {
915 numstr = s.substr(i*15, 15);
916 cf = getNumberFromString(numstr);
922 for (i = 2; i < 5; i++) {
923 numstr = s.substr(i*15, 15);
924 cf = getNumberFromString(numstr);
937 for (i = 0; i < 4; i++) {
938 numstr = s.substr(i*15, 15);
939 cf = getNumberFromString(numstr);
950 void CKParser::missingAuxData(
const std::string& kw)
953 " keyword must be followed by slash-delimited data.",
m_line);
969 vector<string> rc, pr;
975 if (
match(s,
"<EOF>")) {
978 }
while (!
match(s,
"REAC"));
983 getTokens(s, static_cast<int>(s.size()), toks);
988 for (ir = 1; ir < toks.size(); ir++) {
990 if (
match(tok,
"CAL/MOLE")) {
992 }
else if (
match(tok,
"KCAL/MOLE")) {
994 }
else if (
match(tok,
"JOULES/MOLE")) {
996 }
else if (
match(tok,
"KJOULES/MOLE")) {
998 }
else if (
match(tok,
"KELVINS")) {
1000 }
else if (
match(tok,
"EVOLTS")) {
1002 }
else if (
match(tok,
"MOLES")) {
1004 }
else if (
match(tok,
"MOLECULES")) {
1015 *
m_log <<
"CKParser::readReactions ---> DEBUG MODE" << endl;
1023 cm.push_back(comment);
1024 }
while (s ==
"" && comment[0] !=
'%');
1028 *
m_log <<
"Line: " << s << endl;
1035 reactions.push_back(rxn);
1046 string sleft, sright;
1047 bool auxDataLine, metaDataLine;
1055 size_t eqloc = s.find_first_of(
"=");
1056 metaDataLine =
false;
1057 auxDataLine =
false;
1061 metaDataLine =
true;
1062 if (eqloc > 0 && eqloc < s.size()) {
1064 vector<grouplist_t> rg, pg;
1066 ierr =
getGroups(s.begin(), s.begin() + eqloc,
1068 ierp =
getGroups(s.begin() + eqloc, s.end(),
1071 static_cast<unsigned int>(rxn.
reactants.size());
1072 unsigned int nratoms = 0;
1073 for (
unsigned int ij = 0; ij < nr; ij++) {
1074 nratoms += int(rxn.
reactants[ij].number);
1076 if (rg.size() != nratoms)
1078 " groups not specified for all reactants",
m_line);
1081 " error in reactant group specification",
m_line);
1082 for (
unsigned int ir = 0; ir < nr; ir++) {
1086 static_cast<unsigned int>(rxn.
products.size());
1087 unsigned int npatoms = 0;
1088 for (
unsigned int ik = 0; ik < np; ik++) {
1089 npatoms += int(rxn.
products[ik].number);
1091 if (pg.size() != npatoms)
1093 " groups not specified for all products",
m_line);
1096 " error in product group specification",
m_line);
1097 for (
unsigned int ip = 0; ip < np; ip++) {
1106 reactions.push_back(rxn);
1113 *
m_log <<
"Parsing reaction " << nRxns << endl;
1118 if (comment !=
"") {
1119 rxn.
lines.push_back(s+
'!'+comment);
1121 rxn.
lines.push_back(s);
1124 if (!auxDataLine && !metaDataLine) {
1133 sleft = s.substr(0, eqloc);
1134 sright = s.substr(eqloc+3,1000);
1135 }
else if (eqloc = s.find(
"=>"), eqloc !=
string::npos) {
1137 sleft = s.substr(0, eqloc);
1138 sright = s.substr(eqloc+2,1000);
1139 }
else if (eqloc = s.find(
"="), eqloc !=
string::npos) {
1141 sleft = s.substr(0, eqloc);
1142 sright = s.substr(eqloc+1,1000);
1144 "expected <=>, =>, or =",
m_line);
1147 *
m_log << s << endl;
1149 *
m_log <<
"Reaction is reversible." << endl;
1151 *
m_log <<
"Reaction is irreversible." << endl;
1155 string::size_type mloc, mloc2;
1159 *
m_log <<
"Processing reactants..." << sleft << endl;
1162 if (debug) *
m_log <<
"After removing white space: "
1166 string sm, mspecies;
1168 mloc = sleft.find(
"(+");
1170 sm = sleft.substr(mloc+2, 1000);
1171 mloc2 = sm.find(
")");
1173 mspecies = sm.substr(0,mloc2);
1176 sleft = sleft.substr(0, mloc);
1177 if (mspecies ==
"M" || mspecies ==
"m") {
1183 *
m_log <<
"Falloff reaction. Third body = "
1190 else if ((mloc = sleft.find(
"+M"), mloc !=
string::npos) ||
1193 if (static_cast<int>(mloc) ==
1194 static_cast<int>(sleft.size()) - 2) {
1197 sleft = sleft.substr(0, mloc);
1200 *
m_log <<
"Three-body reaction." << endl;
1203 *
m_log <<
"Reactant string contains +M or +m, but \n"
1204 <<
"not last two characters of string: "
1205 <<
"\"" << sleft <<
"\"\n"
1206 <<
"NOT a three-body reaction." << endl;
1210 getSpecies(sleft.c_str(),
static_cast<int>(sleft.size()),
1212 int ir =
static_cast<int>(rxn.
reactants.size());
1213 for (
int iir = 0; iir < ir; iir++) {
1214 if (find(speciesNames.begin(), speciesNames.end(),
1215 rxn.
reactants[iir].name) >= speciesNames.end())
1217 "undeclared reactant species "
1223 getTokens(sright, static_cast<int>(sright.size()), toks);
1224 int ntoks =
static_cast<int>(toks.size());
1227 "expected 3 Arrhenius parameters",
m_line);
1229 rxn.
kf.
A = de_atof(toks[ntoks - 3]);
1230 rxn.
kf.
n = de_atof(toks[ntoks - 2]);
1231 rxn.
kf.
E = de_atof(toks[ntoks - 1]);
1235 *
m_log <<
"Warning: negative prefactor at line "
1240 *
m_log <<
"Processing products..." << sright << endl;
1242 sright = sright.substr(0, sright.find(toks[ntoks - 3]) - 1);
1243 if (debug) *
m_log <<
"After removing Arrhenius parameters, "
1244 <<
"\nproduct string = " << sright << endl;
1247 if (debug) *
m_log <<
"After removing white space: "
1249 mloc = sright.find(
"(+");
1251 sm = sright.substr(mloc+2, 1000);
1252 mloc2 = sm.find(
")");
1254 mspecies = sm.substr(0,mloc2);
1258 "mismatched +M or (+M)",
m_line);
1263 *
m_log <<
"Falloff reaction. Third body = "
1269 sright = sright.substr(0, mloc);
1271 if (mspecies ==
"M" || mspecies ==
"m") {
1276 "mismatched third body",
m_line);
1281 else if ((mloc = sright.find(
"+M"), mloc !=
string::npos) ||
1284 if (static_cast<int>(mloc) ==
1285 static_cast<int>(sright.size()) - 2) {
1289 "mismatched +M or (+M)",
m_line);
1292 sright = sright.substr(0, mloc);
1294 *
m_log <<
"Three-body reaction." << endl;
1297 *
m_log <<
"Product string contains +M or +m, but \n"
1298 <<
"not last two characters of string: "
1299 <<
"\"" << sright <<
"\"\n"
1300 <<
"NOT a three-body reaction." << endl;
1303 getSpecies(sright.c_str(),
static_cast<int>(sright.size()),
1305 int ip =
static_cast<int>(rxn.
products.size());
1306 for (
int iip = 0; iip < ip; iip++) {
1307 if (find(speciesNames.begin(), speciesNames.end(),
1308 rxn.
products[iip].name) >= speciesNames.end())
1315 else if (auxDataLine) {
1319 map<string, int> kwindex;
1323 if (!hasAuxData && name ==
"") {
1328 if (kwindex[name]) {
1330 "duplicate auxiliary data keyword "
1339 if (
match(name,
"LOW")) {
1340 vector<string> klow;
1343 getTokens(data, static_cast<int>(data.size()), klow);
1344 if (klow.size() != 3) {
1346 "expected 3 low-pressure Arrhenius parameters",
m_line);
1348 rxn.
kf_aux.
A = de_atof(klow[0]);
1349 rxn.
kf_aux.
n = de_atof(klow[1]);
1350 rxn.
kf_aux.
E = de_atof(klow[2]);
1352 missingAuxData(
"LOW");
1359 else if (
match(name,
"TROE")) {
1360 vector<string> falloff;
1361 if (kwindex[
"SRI"] > 0) {
1363 "cannot specify both SRI and TROE",
m_line);
1367 getTokens(data, static_cast<int>(data.size()), falloff);
1368 int nf =
static_cast<int>(falloff.size());
1370 rxn.falloffType = Troe;
1371 for (
int jf = 0; jf < nf; jf++) {
1372 ff = de_atof(falloff[jf]);
1373 rxn.falloffParameters.push_back(ff);
1376 missingAuxData(
"TROE");
1380 else if (
match(name,
"SRI")) {
1381 vector<string> falloff;
1382 if (kwindex[
"TROE"] > 0) {
1384 "cannot specify both SRI and TROE",
m_line);
1387 getTokens(data, static_cast<int>(data.size()), falloff);
1388 int nf =
static_cast<int>(falloff.size());
1389 rxn.falloffType = SRI;
1391 for (
int jf = 0; jf < nf; jf++) {
1392 ff = de_atof(falloff[jf]);
1393 rxn.falloffParameters.push_back(ff);
1396 missingAuxData(
"SRI");
1404 else if (
match(name,
"REV")) {
1405 vector<string> krev;
1408 "reverse rate parameters can only be "
1409 "specified for reversible reactions",
m_line);
1412 getTokens(data, static_cast<int>(data.size()), krev);
1413 if (krev.size() != 3) {
1415 "expected 3 Arrhenius parameters",
m_line);
1417 rxn.
krev.
A = de_atof(krev[0]);
1418 rxn.
krev.
n = de_atof(krev[1]);
1419 rxn.
krev.
E = de_atof(krev[2]);
1421 missingAuxData(
"REV");
1426 else if (
match(name,
"DUP")) {
1430 else if (
match(name,
"END")) {
1439 else if (
match(name,
"LT")) {
1441 rxn.
kf.
type = LandauTeller;
1443 getTokens(data, static_cast<int>(data.size()), bc);
1444 rxn.
kf.
B = de_atof(bc[0]);
1445 rxn.
kf.
C = de_atof(bc[1]);
1447 missingAuxData(
"LT");
1451 else if (
match(name,
"RLT")) {
1455 getTokens(data, static_cast<int>(data.size()), bc);
1456 rxn.
krev.
B = de_atof(bc[0]);
1457 rxn.
krev.
C = de_atof(bc[1]);
1459 missingAuxData(
"RLT");
1465 else if (
match(name,
"HIGH")) {
1466 vector<string> khigh;
1469 getTokens(data, static_cast<int>(data.size()), khigh);
1470 rxn.
kf_aux.
A = de_atof(khigh[0]);
1471 rxn.
kf_aux.
n = de_atof(khigh[1]);
1472 rxn.
kf_aux.
E = de_atof(khigh[2]);
1474 missingAuxData(
"HIGH");
1478 else if (
match(name,
"FORD")) {
1479 vector<string> nmord;
1481 getTokens(data, static_cast<int>(data.size()),
1483 rxn.fwdOrder[nmord[0]] = de_atof(nmord[1]);
1485 missingAuxData(
"FORD");
1489 else if (find(speciesNames.begin(), speciesNames.end(), name)
1490 < speciesNames.end()) {
1493 rxn.
e3b[name] = de_atof(data);
1495 *
m_log <<
"Error in reaction " << nRxns
1496 <<
": third-body collision efficiencies cannot be specified"
1497 <<
" for this reaction type." << endl;
1499 "third-body efficiency error",
m_line);
1501 *
m_log <<
"Reaction " << nRxns <<
": illegal species in enhanced "
1502 <<
"efficiency specification. Species = "
1503 << name <<
" rxn.thirdBody = "
1506 "third-body efficiency error",
m_line);
1509 missingAuxData(name);
1513 vector<string> toks;
1514 getTokens(data, static_cast<int>(data.size()), toks);
1515 int ntoks =
static_cast<int>(toks.size());
1516 for (
int itok = 0; itok < ntoks; itok++) {
1517 vals.push_back(de_atof(toks[itok]));
1529 int parseGroupString(std::string str, std::vector<std::string>& esyms, group_t& result)
1532 string s = str +
'-';
1536 string::const_iterator begin = s.begin();
1537 string::const_iterator end = s.end();
1538 vector<string>::iterator e;
1539 result.resize(static_cast<size_t>(esyms.size()),0);
1540 for (; begin != end; ++begin) {
1543 if (*begin ==
'-') {
1544 e = find(esyms.begin(), esyms.end(), sym);
1545 if (e == esyms.end()) {
1548 eindx =
static_cast<int>(e - esyms.begin());
1550 i = atoi(num.c_str());
1558 }
else if (isdigit(*begin)) {
1561 }
else if (isalpha(*begin) && inSymbol) {