38 bool CKReader::read(
const std::string& inputFile,
const std::string& thermoDatabase,
39 const std::string& logfile)
46 ifstream ckinfile(inputFile.c_str());
47 ofstream log(logfile.c_str());
50 CKParser parser(&ckinfile, inputFile, &log);
51 parser.verbose = verbose;
58 newtime = localtime(&aclock);
61 log <<
"CKReader version 1.0" << endl
62 <<
"http://www.cantera.org" << endl << endl
63 << asctime(newtime) << endl
64 << setw(20) <<
"input file: "
65 << setw(30) << inputFile << endl;
67 if (thermoDatabase !=
"")
68 log << setw(20) <<
"species database: "
69 << setw(30) << thermoDatabase << endl;
72 log << endl <<
"*************** Warning ***************" << endl
73 <<
" mechanism validation disabled" << endl
74 <<
"*****************************************" << endl;
77 log <<
"*** DEBUG MODE ***" << endl;
79 log <<
"debugging disabled." << endl;
85 int nel =
static_cast<int>(elements.size());
86 vector<string> elementSymbols;
87 for (
int j = 0; j < nel; j++) {
88 elementSymbols.push_back(elements[j].name);
92 log.flags(ios::showpoint);
96 log << endl <<
newTask(
"reading elements") << endl;
99 for (
int i = 0; i < nel; i++) {
100 log << i+1 <<
". " <<
pad(elements[i].name,2) <<
" ";
101 double wt = elements[i].atomicWeight;
107 if (!elements[i].weightFromDB) {
108 log <<
" (specified)";
110 if (elements[i].comment !=
"") {
111 log <<
" ! " << elements[i].comment;
116 log <<
"\nread " << nel <<
" elements." << endl;
119 log <<
"\nerrors were encountered." << endl;
129 vector<string> speciesSymbols;
131 int nsp =
static_cast<int>(species.size());
134 log <<
newTask(
"reading species") << endl;
137 for (
int i = 0; i < nsp; i++) {
140 log << i+1 <<
". " << s.
name << endl;
142 speciesSymbols.push_back(s.
name);
144 log <<
"\nread " << nsp <<
" species." << endl;
147 log <<
"\nerrors were encountered." << endl;
158 log <<
newTask(
"looking up species definitions") << endl;
164 if (thermoDatabase !=
"") {
166 if (verbose) log <<
"reading default temperature ranges from "
167 << thermoDatabase << endl;
169 ifstream thermofile(thermoDatabase.c_str());
170 CKParser thermReader(&thermofile, thermoDatabase, &log);
171 thermReader.verbose = verbose;
172 thermReader.debug = debug;
173 int dbflag = HasTempRange;
174 vector<string> dummy;
175 thermReader.readThermoSection(dummy, speciesData, temp, dbflag, log);
179 bool hasthermo = parser.advanceToKeyword(
"THERM",
"REAC");
181 int k, optionFlag = 0;
182 int undefined =
static_cast<int>(species.size());
184 vector<string> undef;
185 bool allsp = (speciesSymbols[0] ==
"<ALL>");
188 speciesData, temp, optionFlag, log)) {
190 nsp =
static_cast<int>(speciesData.size());
191 for (k = 0; k < nsp; k++) {
193 s.
name = speciesSymbols[k];
194 species.push_back(s);
198 for (k = 0; k < nsp; k++) {
199 nm = species[k].name;
200 species[k] = speciesData[species[k].name];
201 if (species[k].name ==
"<empty>") {
204 species[k].name = nm;
207 int localdefs = nsp - undefined;
208 if (localdefs > 0 && verbose) log <<
"found definitions for "
212 <<
" species in the input file. "
215 undef = speciesSymbols;
217 log <<
"no THERMO section in input file." << endl;
221 if (undefined > 0 && thermoDatabase !=
""
224 if (verbose) log <<
"searching external database "
225 << thermoDatabase <<
" for species definitions..."
228 ifstream thermofile(thermoDatabase.c_str());
229 CKParser thermoReader(&thermofile, thermoDatabase, &log);
230 thermoReader.verbose = verbose;
231 thermoReader.debug = debug;
232 int dbflag = HasTempRange;
233 thermoReader.readThermoSection(undef, speciesData, temp, dbflag, log);
237 nsp =
static_cast<int>(speciesData.size());
238 for (k = 0; k < nsp; k++) {
241 species.push_back(s);
244 for (
int k = 0; k < nsp; k++) {
245 if (species[k].
valid == 0) {
246 nm = species[k].name;
247 species[k] = speciesData[species[k].name];
248 if (species[k].name ==
"<empty>") {
250 species[k].name = nm;
256 if (validate && !validateSpecies(log)) {
265 log <<
newTask(
"reading reactions") << endl;
269 ifstream ckinfile2(inputFile.c_str());
272 CKParser parser2(&ckinfile2, inputFile, &log);
273 parser2.verbose = verbose;
274 parser2.debug = debug;
276 parser2.readReactionSection(speciesSymbols, elementSymbols, reactions, units);
277 log <<
"\nread " <<
static_cast<int>(reactions.size())
278 <<
" reactions." << endl;
282 rxnok = rxnok && validateReactions(log);
285 if (verbose || validate) {
286 writeok = writeReactions(log);
288 rxnok = rxnok && writeok;
293 log <<
"\nSuccess... ";
295 log <<
"elapsed CPU time = "
296 << double(t1 - t0)/CLOCKS_PER_SEC
299 log <<
"*** no validation performed ***" << endl;
303 catch (CK_Exception& e) {
304 log << e.errorMessage() << endl;
307 }
catch (std::exception& e) {
308 log <<
"an exception was raised in CKReader:\n";
309 log << e.what() << std::endl;
318 bool CKReader::writeReactions(std::ostream& log)
323 int nrxns =
static_cast<int>(reactions.size());
324 log.flags(ios::unitbuf);
328 for (
int n = 0; n < nrxns; n++) {
331 log <<
"reaction " << r.
number << endl;
339 log <<
" high P rate coeff: ";
342 log <<
" low P rate coeff: ";
345 ok = ok &&
writeFalloff(r.falloffType, r.falloffParameters, log);
348 log <<
" rate coeff: ";
352 log <<
" reverse rate coeff: ";
355 int ne =
static_cast<int>(r.
e3b.size());
358 vector<string> enhSpecies;
360 log <<
" enhanced collision efficiencies:" << endl;
362 for (
int nn = 0; nn < ne; nn++) {
363 log << enhSpecies[nn] <<
" "
364 << r.
e3b[enhSpecies[nn]];
372 <<
" declared duplicate reaction. See reaction "
382 bool CKReader::validateSpecies(std::ostream& log)
384 size_t nel = elements.size();
385 size_t nsp = species.size();
388 log <<
newTask(
"validating species");
391 vector<string> esyms;
393 log <<
" checking that all species have been defined... ";
394 for (
size_t k = 0; k < nsp; k++) {
397 log << endl <<
" species " << s.
name <<
" undefined ";
401 if (
valid(species)) {
408 log <<
" checking that all species elements have been declared... ";
409 for (
size_t k = 0; k < nsp; k++) {
413 size_t nm = esyms.size();
415 for (
size_t m = 0; m < nm; m++) {
417 for (j = 0; j < nel; j++) {
418 if (esyms[m] == elements[j].name) {
423 log << endl <<
" species "
424 << s.
name <<
": undeclared element "
430 if (
valid(species)) {
437 log <<
" checking consistency of species thermo data... ";
451 bool CKReader::validateReactions(std::ostream& log)
456 int nrxns =
static_cast<int>(reactions.size());
459 log <<
"checking that all reactions balance...";
461 log <<
" OK" << endl;
463 int nu =
static_cast<int>(unbal.size());
464 for (
int iu = 0; iu < nu; iu++) {
465 log <<
" error... reaction " << unbal[iu]
466 <<
" does not balance" << endl;
471 log <<
"checking for duplicate reactions...";
473 for (
int nn = 0; nn < nrxns; nn++) {
475 for (
int mm = nn + 1; mm < nrxns; mm++) {
481 log << endl <<
" error... undeclared duplicate reactions: "
482 << nn + 1 <<
" and " << mm + 1;
485 log << endl <<
" declared duplicate reactions: "
487 <<
" and " << mm + 1;
493 log <<
"...OK" << endl;
513 const double dt = 0.0001;
514 double t, cp0, h0, s0, cp1, h1, s1;
515 int nsp =
static_cast<int>(sp.size());
516 const int n_points = 20;
520 for (k = 0; k < nsp; k++) {
525 log << endl <<
"species " << s.
name
526 <<
" contains an error." << endl;
533 log << endl <<
" Checking that cp/R is positive... ";
535 for (k = 0; k < nsp; k++) {
541 for (
int j = 0; j < n_points; j++) {
546 log << endl <<
" error... Cp/R < 0 at T = " << t
547 <<
" for species " << s.
name << endl;
562 log <<
" Checking that the species entropies are positive... ";
563 for (k = 0; k < nsp; k++) {
566 log << endl <<
" error... negative entropy for species "
578 log <<
" Checking that properties are continuous at the midpoint temperature... ";
579 for (k = 0; k < nsp; k++) {
593 if (
absval((cp0 - cp1)/cp0) > tol) {
594 log << endl <<
"Warning... species " << s.
name
595 <<
": discontinuity in Cp at Tmid = "
597 log <<
"Cp/R (low, high) = " << cp0
598 <<
", " << cp1 << endl;
602 if (
absval((h0 - h1)/h0) > tol) {
603 log << endl <<
"Warning... species " << s.
name
604 <<
": discontinuity in enthalpy at Tmid = "
606 log <<
"h/R (low, high) = "
607 << h0 <<
", " << h1 << endl;
611 if (
absval((s0 - s1)/s0) > tol) {
612 log << endl <<
"Warning... species " << s.
name
613 <<
": discontinuity in entropy at Tmid = "
615 log <<
"s/R (low, high) = "
616 << s0 <<
", " << s1 << endl;
626 log <<
" Checking that cp is less that the high-temperature\n"
627 <<
" limiting value predicted by equipartition of energy.\n";
628 log <<
" Note that this limit does not account for the electronic\n"
629 <<
" contribution to cp, and so may be violated in some cases."
633 for (k = 0; k < nsp; k++) {
640 int nel =
static_cast<int>(s.
elements.size());
643 for (i = 0; i < nel; i++)
647 int natoms = int(floor(na));
657 cpmax = 3.0*natoms - 3.0;
661 double over = 100.0*(cp0 - cpmax)/cpmax;
662 log << endl <<
"Warning... species " << s.
name
663 <<
": cp(Tmax) greater than equipartition value \nby "
664 << over <<
" percent.";
665 if ((natoms > 2) && (cp0 - cpmax < 0.5))
666 log << endl <<
" (if molecule is linear, cp is ok)"
687 reactionList& r, std::vector<int>& unbalanced,
double tolerance)
689 int nrxn =
static_cast<int>(r.size());
691 vector<string> elementSyms;
695 map<string, double> atoms;
697 for (
int i = 0; i < nrxn; i++) {
699 int nr =
static_cast<int>(r[i].reactants.size());
700 int np =
static_cast<int>(r[i].products.size());
703 for (j = 0; j < nr; j++) {
704 rname = r[i].reactants[j].name;
705 stoichCoeff = r[i].reactants[j].number;
706 vector<Constituent>& elements = speciesData[rname].elements;
707 for (m = 0; m < elements.size(); m++) {
708 atoms[elements[m].name] -= stoichCoeff * elements[m].number;
711 for (j = 0; j < np; j++) {
712 pname = r[i].products[j].name;
713 stoichCoeff = r[i].products[j].number;
714 vector<Constituent>& elements = speciesData[pname].elements;
715 for (m = 0; m < elements.size(); m++) {
716 atoms[elements[m].name] += stoichCoeff * elements[m].number;
721 for (m = 0; m < elementSyms.size(); m++) {
722 atms = atoms[elementSyms[m]];
723 if (fabs(atms) > tolerance) {
728 unbalanced.push_back(i+1);
733 return (unbalanced.empty());