missing EOF
[OpenFOAM-1.6.x.git] / src / thermophysicalModels / reactionThermo / chemistryReaders / chemkinReader / chemkinLexer.L
blobdc2d0e7830c801fa6eb90043b6b61d80d34cb79c
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 1991-2009 OpenCFD Ltd.
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
9     This file is part of OpenFOAM.
11     OpenFOAM is free software; you can redistribute it and/or modify it
12     under the terms of the GNU General Public License as published by the
13     Free Software Foundation; either version 2 of the License, or (at your
14     option) any later version.
16     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19     for more details.
21     You should have received a copy of the GNU General Public License
22     along with OpenFOAM; if not, write to the Free Software Foundation,
23     Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
29 #undef yyFlexLexer
31 #include "chemkinReader.H"
33 #include "error.H"
34 #include "IStringStream.H"
35 // For EOF only
36 #include <cstdio>
38 // flex input buffer size
39 int Foam::chemkinReader::yyBufSize = YY_BUF_SIZE;
41 // Dummy yyFlexLexer::yylex() to keep the linker happy. It is not called
42 //! @cond dummy
43 int yyFlexLexer::yylex()
45     Foam::FatalErrorIn("yyFlexLexer::yylex()")
46         << "should not have called this function"
47         << abort(Foam::FatalError);
49     return 0;
51 //! @endcond dummy
54 // Dummy yywrap to keep yylex happy at compile time.
55 // It is called by yylex but is not used as the mechanism to change file.
56 // See <<EOF>>
57 //! @cond dummy
58 #if YY_FLEX_SUBMINOR_VERSION < 34
59 extern "C" int yywrap()
60 #else
61 int yyFlexLexer::yywrap()
62 #endif
64     return 1;
66 //! @endcond dummy
69 Foam::string foamSpecieString(const char* YYText)
71     Foam::string specieString(YYText);
72     // Transforming parentheses is no longer necessary
73     //specieString.replaceAll('(', '<');
74     //specieString.replaceAll(')', '>');
75     return specieString;
79 Foam::word foamName(const char* YYText)
81     Foam::string fn(YYText);
82     Foam::string::stripInvalid<Foam::word>(fn);
83     return fn;
87 Foam::word foamName(const Foam::string& s)
89     Foam::string fn(s);
90     Foam::string::stripInvalid<Foam::word>(fn);
91     return fn;
95  /* ------------------------------------------------------------------------- *\
96    ------ cppLexer::yylex()
97  \* ------------------------------------------------------------------------- */
99 #define YY_DECL int Foam::chemkinReader::lex()
103 one_space             [ \t\f\r]
104 space                 {one_space}*
105 some_space            {one_space}+
106 cspace                ","{space}
108 alpha                 [_A-Za-z]
109 digit                 [0-9]
110 dec_digit             [0-9]
111 octal_digit           [0-7]
112 hex_digit             [0-9a-fA-F]
114 identifier            {alpha}({alpha}|{digit})*
115 integer               {dec_digit}+
116 label                 [1-9]{dec_digit}*
117 zeroLabel             {digit}*
119 word                  ([[:alnum:]]|[[:punct:]])+
120 string                {word}({some_space}{word})*
122 exponent_part         [eEdD][-+]?{digit}+
123 fractional_constant   [-+]?(({digit}*"."{digit}+)|({digit}+"."?))
125 double                (({fractional_constant}{exponent_part}?)|({digit}+{exponent_part}))
128 elements              {space}("ELEMENTS"|"ELEM"){space}
129 species               {space}("SPECIES"|"SPECIE"|"SPEC"){space}
130 thermoAll             {space}"THERMO"{some_space}"ALL"{space}
131 thermo                {space}"THERMO"{space}
132 reactions             {space}("REACTIONS"|"REAC"){space}
133 end                   {space}"END"{space}
135 elementName           {space}([A-Z]|([A-Z][A-Z])){space}
136 startIsotopeMolW      {space}"/"{space}
137 isotopeMolW           {space}{double}{space}"/"{space}
139 specieName            {space}[A-Za-z](([A-Za-z0-9)*+-])|("("[^+]))*{space}
140 nMoles                {space}{double}{space}
142 thermoTemp            .{10}
144 thermoSpecieName      .{18}
145 thermoDate            .{6}
146 thermoFormula         .{20}
147 thermoPhase           S|L|G
148 thermoLowTemp         .{10}
149 thermoHighTemp        .{10}
150 thermoCommonTemp      .{8}
151 thermoFormula2        .{5}
152 thermoCoeff           .{15}
153 thermoLineLabel1      " "1{space}
154 thermoLineLabel2      " "{4}2{space}
155 thermoLineLabel3      " "{4}3{space}
156 thermoLineLabel4      " "{4}4{space}
158 specieDelimiter       {space}"+"{space}
159 reversibleReactionDelimiter {space}("="|"<=>"){space}
160 irreversibleReactionDelimiter {space}"=>"{space}
161 startPDependentSpecie {space}"("{space}"+"{space}
162 pDependentSpecie      {specieName}")"{space}
163 reactionCoeffs        {space}{double}{some_space}{double}{some_space}{double}{space}
164 reactionKeyword       {space}[A-Za-z](([A-Za-z0-9)*-])|("("[^+]))*{space}
165 reactionKeywordSlash  {reactionKeyword}"/"{space}
166 thirdBodyEfficiency   {space}{double}{space}"/"{space}
167 startReactionCoeffs   {space}"/"{space}
168 endReactionCoeffs     {space}"/"{space}
169 reactionCoeff         {space}{double}{space}
171 calPerMol             {space}"CAL/MOLE"{space}
172 kcalPerMol            {space}"KCAL/MOLE"{space}
173 joulePerMol           {space}"JOULES/MOLE"{space}
174 otherReactionsUnit    {space}("KELVINS"|"EVOLTS"|"MOLES"|"MOLECULES"){space}
176 cal                   {space}"CAL"{space}
177 kcal                  {space}"KCAL"{space}
178 joule                 {space}"JOUL"{space}
179 kjoule                {space}"KJOU"{space}
180 otherReactionUnit     {space}("MOLE"|"MOLECULE"|"KELV"|"KELVIN"|"EVOL"|"EVOLTS"){space}
183  /* ------------------------------------------------------------------------- *\
184                       -----  Exclusive start states -----
185  \* ------------------------------------------------------------------------- */
187 %option stack
189 %x readElements
190 %x readIsotopeMolW
191 %x readSpecies
192 %x readThermoAll
193 %x readThermoSpecieName
194 %x readThermoDate
195 %x readThermoFormula
196 %x readThermoPhase
197 %x readThermoTemps
198 %x readThermoFormula2
199 %x readThermoLineLabel1
200 %x readThermoCoeff1
201 %x readThermoLineLabel2
202 %x readThermoCoeff2
203 %x readThermoLineLabel3
204 %x readThermoCoeff3
205 %x readThermoLineLabel4
206 %x readReactionsUnits
207 %x readReactionKeyword
208 %x readSpecieNamePlus
209 %x readReactionDelimiter
210 %x readPDependentSpecie
211 %x readThirdBodyEfficiency
212 %x readReactionCoeffs
213 %x readTdepSpecie
214 %x readReactionOrderSpecie
215 %x readReactionOrder
216 %x readReactionUnit
217 %x CHEMKINError
223 static const char* stateNames[30] =
225     "reading CHEMKIN III file",
226     "reading elements",
227     "reading isotope molecular weight",
228     "reading species",
229     "reading all thermodynamic data temperatures",
230     "reading thermodynamic specie name",
231     "reading thermodynamic data date",
232     "reading thermodynamic data specie formula",
233     "reading thermodynamic data specie phase",
234     "reading thermodynamic data temperatures",
235     "reading thermodynamic data specie formula (supplement)",
236     "reading thermodynamic data line label 1",
237     "reading thermodynamic data coefficient set 1",
238     "reading thermodynamic data line label 2",
239     "reading thermodynamic data coefficient set 2",
240     "reading thermodynamic data line label 3",
241     "reading thermodynamic data coefficient set 3",
242     "reading thermodynamic data line label 4",
243     "reading reaction units",
244     "reading reaction specie/keyword",
245     "reading reaction specie",
246     "reading reaction delimiter",
247     "reading reaction pressure dependent specie",
248     "reading third-body efficiency",
249     "reading reaction coeff",
250     "reading temperature dependent specie name",
251     "reading reaction order specie name",
252     "reading reaction order",
253     "reading reaction unit",
254     "error"
257 static const char* stateExpects[30] =
259     "'ELEMENTS' or 'ELEM', 'SPECIES' or 'SPEC', 'THERMO' or 'THERMO ALL', 'REACTIONS'",
260     "<elementName>, <isotopeName> / or 'END'",
261     "<scalar>/",
262     "<specieName> or 'END'",
263     "<scalar><scalar><scalar> (3F10.0)",
264     "<word> (18A1)",
265     "<word> (6A1)",
266     "<word><label><word><label><word><label><word><label> (4(2A1,I3))",
267     "<char> (A1)",
268     "<scalar><scalar><scalar> (E10.0E10.0E8.0)",
269     "<word><label> (2A1,I3)",
270     "'1' (I1)",
271     "<scalar><scalar><scalar><scalar><scalar> (5(E15.0))",
272     "'2' (I1)",
273     "<scalar><scalar><scalar><scalar><scalar> (5(E15.0))",
274     "'3' (I1)",
275     "<scalar><scalar><scalar><scalar> (4(E15.0))",
276     "'4' (I1)",
277     "'CAL/MOLE', 'KCAL/MOLE', 'JOULES/MOLE', 'KELVINS', 'EVOLTS', 'MOLES' or 'MOLECULES'",
278     "<word> or <label>",
279     "'+'",
280     "'+', '=', '<=>', '=>', '(+<word>', '<scalar> <scalar> <scalar>'",
281     "<word>')'",
282     "<scalar>'/'",
283     "<scalar>",
284     "<word>",
285     "<word>",
286     "<scalar>",
287     "'MOLE', 'MOLECULE', 'CAL', 'KCAL', 'JOUL', 'KJOU', 'KELV', 'KELVIN', 'EVOL' or 'EVOLTS'",
288     ""
291 string startError;
293 static const scalar RRjoule = 8.31451; // J/kg-mol-K
294 static const scalar RRcal = 1.987316;  // cal/g-mol-K
296 scalar RRreactions = RRcal;
297 scalar RRreaction = RRcal;
299 scalar allCommonT = 1000.0;
301 word currentElementName;
302 label currentElementIndex = 0;
304 word currentSpecieName;
305 label currentSpecieIndex = 0;
306 label nSpecieElements = 0;
307 List<specieElement> currentSpecieComposition(5);
309 scalar currentLowT = 0;
310 scalar currentHighT = 0;
311 scalar currentCommonT = 0;
312 gasThermoPhysics::coeffArray highCpCoeffs;
313 gasThermoPhysics::coeffArray lowCpCoeffs;
315 gasReaction::specieCoeffs currentSpecieCoeff;
317 DynamicList<gasReaction::specieCoeffs> lhs;
318 DynamicList<gasReaction::specieCoeffs> rhs;
320 scalarList ArrheniusCoeffs(3);
321 DynamicList<scalar> reactionCoeffs;
322 scalarList thirdBodyEfficiencies;
323 label currentThirdBodyIndex = -1;
325 word reactionCoeffsName = word::null;
326 HashTable<scalarList> reactionCoeffsTable;
328 DynamicList<gasReaction::specieCoeffs> *lrhsPtr = &lhs;
330 reactionType rType = unknownReactionType;
331 reactionRateType rrType = Arrhenius;
332 fallOffFunctionType fofType = unknownFallOffFunctionType;
333 word pDependentSpecieName = word::null;
334 label lhsThirdBodyCounter = 0;
335 label rhsThirdBodyCounter = 0;
337 bool finishReaction = false;
341  /* ------------------------------------------------------------------------- *\
342                             ------ Start Lexing ------
343  \* ------------------------------------------------------------------------- */
345  /* ------------------------------------------------------------------------- *\
346     ------ Discard comments being careful to count comments
347  \* ------------------------------------------------------------------------- */
349 <*>{space}"!".* { // Remove one line comments
350     }
352  /* ------------------------------------------------------------------------- *\
353     ------ Read elements
354  \* ------------------------------------------------------------------------- */
356 {elements} {
357         BEGIN(readElements);
358     }
360 <readElements>{elementName} {
361         currentElementName = foamName(YYText());
362         correctElementName(currentElementName);
364         if (!elementIndices_.found(currentElementName))
365         {
366             elementIndices_.insert(currentElementName, currentElementIndex++);
367             elementNames_.append(currentElementName);
368         }
369         else
370         {
371             WarningIn("chemkinReader::lex()")
372                 << "element " << currentElementName
373                 << " already in table." << endl;
374         }
375     }
377 <readElements>{startIsotopeMolW} {
378         BEGIN(readIsotopeMolW);
379     }
381 <readIsotopeMolW>{isotopeMolW} {
382         isotopeAtomicWts_.insert(currentElementName, stringToScalar(YYText()));
383         BEGIN(readElements);
384     }
386 <readElements>{end} {
387         BEGIN(INITIAL);
388     }
390  /* ------------------------------------------------------------------------- *\
391     ------ Read species
392  \* ------------------------------------------------------------------------- */
394 <INITIAL,readElements>{species} {
395         BEGIN(readSpecies);
396     }
398 <readSpecies>{specieName} {
399         word specieName(foamName(foamSpecieString(YYText())));
401         if (specieName == "THERMO")
402         {
403             specieNames_.shrink();
404             speciesTable_ = specieNames_;
405             thirdBodyEfficiencies.setSize(specieNames_.size());
406             thirdBodyEfficiencies = 1.0;
407             BEGIN(readThermoSpecieName);
408         }
409         else if (specieName == "END")
410         {
411             specieNames_.shrink();
412             speciesTable_ = specieNames_;
413             thirdBodyEfficiencies.setSize(specieNames_.size());
414             thirdBodyEfficiencies = 1.0;
415             BEGIN(INITIAL);
416         }
417         else
418         {
419             if (!specieIndices_.found(specieName))
420             {
421                 specieNames_.append(specieName);
422                 specieIndices_.insert(specieName, currentSpecieIndex++);
423             }
424             else
425             {
426                 WarningIn("chemkinReader::lex()")
427                     << "specie " << specieName
428                     << " already in table." << endl;
429             }
430         }
431     }
433  /* ------------------------------------------------------------------------- *\
434     ------ Read thermo
435  \* ------------------------------------------------------------------------- */
437 <INITIAL,readSpecies>{thermo} {
438         BEGIN(readThermoSpecieName);
439     }
441 <INITIAL,readSpecies>{thermoAll} {
442         BEGIN(readThermoAll);
443     }
445 <readThermoAll>{thermoTemp}{thermoTemp}{thermoTemp} {
446         string temperaturesString(YYText());
447         //scalar lowestT(stringToScalar(temperaturesString(0, 10)));
448         allCommonT = stringToScalar(temperaturesString(10, 10));
449         //scalar highestT(stringToScalar(temperaturesString(20, 10)));
450         BEGIN(readThermoSpecieName);
451     }
453 <readThermoSpecieName>{thermoSpecieName} {
454         string specieString(foamSpecieString(YYText()));
455         size_t spacePos = specieString.find(' ');
456         if (spacePos != string::npos)
457         {
458             currentSpecieName = specieString(0, spacePos);
459         }
460         else
461         {
462             currentSpecieName = specieString;
463         }
464         BEGIN(readThermoDate);
465     }
467 <readThermoDate>{thermoDate} {
468         // string thermoDate(YYText());
469         // Date is not currently used
470         BEGIN(readThermoFormula);
471     }
473 <readThermoFormula>{thermoFormula} {
474         string thermoFormula(YYText());
476         nSpecieElements = 0;
477         currentSpecieComposition.setSize(5);
479         for (int i=0; i<4; i++)
480         {
481             word elementName(foamName(thermoFormula(5*i, 2)));
482             label nAtoms = atoi(thermoFormula(5*i + 2, 3).c_str());
484             if (elementName.size() && nAtoms)
485             {
486                 correctElementName(elementName);
487                 currentSpecieComposition[nSpecieElements].elementName =
488                     elementName;
489                 currentSpecieComposition[nSpecieElements++].nAtoms = nAtoms;
490             }
491         }
493         BEGIN(readThermoPhase);
494     }
496 <readThermoPhase>{thermoPhase} {
497         char phaseChar = YYText()[0];
499         switch (phaseChar)
500         {
501             case 'S':
502                 speciePhase_.insert(currentSpecieName, solid);
503             break;
505             case 'L':
506                 speciePhase_.insert(currentSpecieName, liquid);
507             break;
509             case 'G':
510                 speciePhase_.insert(currentSpecieName, gas);
511             break;
512         }
514         BEGIN(readThermoTemps);
515     }
517 <readThermoTemps>{thermoLowTemp}{thermoHighTemp}{thermoCommonTemp} {
518         string temperaturesString(YYText());
519         currentLowT = stringToScalar(temperaturesString(0, 10));
520         currentHighT = stringToScalar(temperaturesString(10, 10));
521         currentCommonT = stringToScalar(temperaturesString(20, 8));
523         if (currentCommonT < SMALL)
524         {
525             currentCommonT = allCommonT;
526         }
528         BEGIN(readThermoFormula2);
529     }
531 <readThermoFormula2>{thermoFormula2} {
532         string thermoFormula(YYText());
533         word elementName(foamName(thermoFormula(0, 2)));
534         label nAtoms = atoi(thermoFormula(2, 3).c_str());
536         if
537         (
538             elementName.size()
539          && elementName.find('0') == string::npos
540          && nAtoms
541         )
542         {
543             correctElementName(elementName);
544             currentSpecieComposition[nSpecieElements].elementName =
545                 elementName;
546             currentSpecieComposition[nSpecieElements++].nAtoms = nAtoms;
547         }
549         currentSpecieComposition.setSize(nSpecieElements);
551         HashTable<List<specieElement> >::iterator specieCompositionIter
552         (
553             specieComposition_.find(currentSpecieName)
554         );
556         if (specieCompositionIter != specieComposition_.end())
557         {
558             specieComposition_.erase(specieCompositionIter);
559         }
561         specieComposition_.insert
562         (
563             currentSpecieName,
564             currentSpecieComposition
565         );
567         BEGIN(readThermoLineLabel1);
568     }
570 <readThermoLineLabel1>{thermoLineLabel1} {
571         BEGIN(readThermoCoeff1);
572     }
574 <readThermoCoeff1>{thermoCoeff}{thermoCoeff}{thermoCoeff}{thermoCoeff}{thermoCoeff} {
575         string thermoCoeffString(YYText());
577         highCpCoeffs[0] = stringToScalar(thermoCoeffString(0, 15));
578         highCpCoeffs[1] = stringToScalar(thermoCoeffString(15, 15));
579         highCpCoeffs[2] = stringToScalar(thermoCoeffString(30, 15));
580         highCpCoeffs[3] = stringToScalar(thermoCoeffString(45, 15));
581         highCpCoeffs[4] = stringToScalar(thermoCoeffString(60, 15));
583         BEGIN(readThermoLineLabel2);
584     }
586 <readThermoLineLabel2>{thermoLineLabel2} {
587         BEGIN(readThermoCoeff2);
588     }
590 <readThermoCoeff2>{thermoCoeff}{thermoCoeff}{thermoCoeff}{thermoCoeff}{thermoCoeff} {
591         string thermoCoeffString(YYText());
593         highCpCoeffs[5] = stringToScalar(thermoCoeffString(0, 15));
594         highCpCoeffs[6] = stringToScalar(thermoCoeffString(15, 15));
596         lowCpCoeffs[0] = stringToScalar(thermoCoeffString(30, 15));
597         lowCpCoeffs[1] = stringToScalar(thermoCoeffString(45, 15));
598         lowCpCoeffs[2] = stringToScalar(thermoCoeffString(60, 15));
600         BEGIN(readThermoLineLabel3);
601     }
603 <readThermoLineLabel3>{thermoLineLabel3} {
604         BEGIN(readThermoCoeff3);
605     }
607 <readThermoCoeff3>{thermoCoeff}{thermoCoeff}{thermoCoeff}{thermoCoeff}{thermoCoeff} {
608         string thermoCoeffString(YYText());
610         lowCpCoeffs[3] = stringToScalar(thermoCoeffString(0, 15));
611         lowCpCoeffs[4] = stringToScalar(thermoCoeffString(15, 15));
612         lowCpCoeffs[5] = stringToScalar(thermoCoeffString(30, 15));
613         lowCpCoeffs[6] = stringToScalar(thermoCoeffString(45, 15));
615         BEGIN(readThermoLineLabel4);
616     }
618 <readThermoLineLabel4>{thermoLineLabel4} {
620         HashPtrTable<gasThermoPhysics>::iterator specieThermoIter
621         (
622             speciesThermo_.find(currentSpecieName)
623         );
625         if (specieThermoIter != speciesThermo_.end())
626         {
627             speciesThermo_.erase(specieThermoIter);
628         }
630         speciesThermo_.insert
631         (
632             currentSpecieName,
633             new gasThermoPhysics
634             (
635                 janafThermo<perfectGas>
636                 (
637                     specie
638                     (
639                         currentSpecieName,
640                         1.0,
641                         molecularWeight(currentSpecieComposition)
642                     ),
643                     currentLowT,
644                     currentHighT,
645                     currentCommonT,
646                     highCpCoeffs,
647                     lowCpCoeffs
648                 ),
649                 1.67212e-6,
650                 170.672
651             )
652         );
654         BEGIN(readThermoSpecieName);
655     }
657 <readThermoSpecieName>{end} {
658         BEGIN(INITIAL);
659     }
661  /* ------------------------------------------------------------------------- *\
662     ------ Read reactions
663  \* ------------------------------------------------------------------------- */
665 <INITIAL,readThermoSpecieName>{reactions} {
666         currentSpecieCoeff.stoichCoeff = 1.0;
667         currentSpecieCoeff.exponent = currentSpecieCoeff.stoichCoeff;
668         BEGIN(readReactionsUnits);
669     }
671 <readReactionsUnits>{calPerMol} {
672         RRreactions = RRcal;
673     }
675 <readReactionsUnits>{kcalPerMol} {
676         RRreactions = RRcal/1000.0;
677     }
679 <readReactionsUnits>{joulePerMol} {
680         RRreactions = RRjoule;
681     }
683 <readReactionsUnits>{otherReactionsUnit} {
684     }
686 <readReactionsUnits>\n {
687         lineNo_++;
688         BEGIN(readReactionKeyword);
689     }
691 <readReactionKeyword>{nMoles} {
692         currentSpecieCoeff.stoichCoeff = atof(YYText());
693         currentSpecieCoeff.exponent = currentSpecieCoeff.stoichCoeff;
694     }
696 <readReactionKeyword>{reactionKeyword} {
698         word keyword(foamName(YYText()));
700         HashTable<int>::iterator reactionKeywordIter
701         (
702             reactionKeywordTable_.find(keyword)
703         );
705         if (reactionKeywordIter != reactionKeywordTable_.end())
706         {
707             switch(reactionKeywordIter())
708             {
709                 case duplicateReactionType:
710                 {
711                     BEGIN(readReactionKeyword);
712                     break;
713                 }
715                 case thirdBodyReactionType:
716                 {
717                     if (rrType != Arrhenius && rrType != thirdBodyArrhenius)
718                     {
719                         FatalErrorIn("chemkinReader::lex()")
720                             << "Attempt to set reaction rate type to"
721                                " thirdBodyArrhenius when it is already set to "
722                             << reactionRateTypeNames[rrType]
723                             << " on line " << lineNo_
724                             << exit(FatalError);
725                     }
727                     if (pDependentSpecieName.size())
728                     {
729                         FatalErrorIn("chemkinReader::lex()")
730                             << "A non-pressure dependent third-body appears in"
731                                " the pressure dependent reaction on line "
732                             << lineNo_
733                             << exit(FatalError);
734                     }
736                     rrType = thirdBodyArrhenius;
738                     if (lrhsPtr == &lhs)
739                     {
740                         lhsThirdBodyCounter++;
741                     }
742                     else
743                     {
744                         rhsThirdBodyCounter++;
745                     }
747                     BEGIN(readReactionDelimiter);
748                     break;
749                 }
751                 case plasmaMomentumTransfer:
752                 {
753                     FatalErrorIn("chemkinReader::lex()")
754                         << "Plasma momentum-transfer in reaction on line "
755                         << lineNo_ << "not yet supported"
756                         << exit(FatalError);
758                     BEGIN(readReactionKeyword);
759                     break;
760                 }
762                 case collisionCrossSection:
763                 {
764                     FatalErrorIn("chemkinReader::lex()")
765                         << "Collision cross-section in reaction on line "
766                         << lineNo_ << "not yet supported"
767                         << exit(FatalError);
769                     BEGIN(readReactionKeyword);
770                     break;
771                 }
773                 case end:
774                 {
775                     BEGIN(INITIAL);
776                     addReaction
777                     (
778                         lhs,
779                         rhs,
780                         thirdBodyEfficiencies,
781                         rType,
782                         rrType,
783                         fofType,
784                         ArrheniusCoeffs,
785                         reactionCoeffsTable,
786                         RRreaction
787                     );
788                     finishReaction = false;
789                     rType = unknownReactionType;
790                     rrType = Arrhenius;
791                     fofType = unknownFallOffFunctionType;
792                     thirdBodyEfficiencies = 1.0;
793                     pDependentSpecieName = word::null;
794                     lrhsPtr = &lhs;
795                     break;
796                 }
798                 default:
799                 {
800                     FatalErrorIn("chemkinReader::lex()")
801                         << "keyword " << keyword
802                         << " should be followed by parameters"
803                         << " on line " << lineNo_
804                         << exit(FatalError);
805                 }
806             }
807         }
808         else
809         {
810             currentSpecieName = foamName(foamSpecieString(YYText()));
812             HashTable<label>::iterator specieIndexIter
813             (
814                 specieIndices_.find(currentSpecieName)
815             );
817             if (specieIndexIter != specieIndices_.end())
818             {
819                 if (finishReaction)
820                 {
821                     addReaction
822                     (
823                         lhs,
824                         rhs,
825                         thirdBodyEfficiencies,
826                         rType,
827                         rrType,
828                         fofType,
829                         ArrheniusCoeffs,
830                         reactionCoeffsTable,
831                         RRreaction
832                     );
833                     finishReaction = false;
834                     rType = unknownReactionType;
835                     rrType = Arrhenius;
836                     fofType = unknownFallOffFunctionType;
837                     thirdBodyEfficiencies = 1.0;
838                     pDependentSpecieName = word::null;
839                     lrhsPtr = &lhs;
840                 }
842                 currentSpecieCoeff.index = specieIndexIter();
843                 lrhsPtr->append(currentSpecieCoeff);
845                 BEGIN(readReactionDelimiter);
846             }
847             else
848             {
849                 BEGIN(readSpecieNamePlus);
850             }
851         }
852     }
854 <readReactionKeyword>{reactionKeywordSlash} {
856         word keyword(foamName(YYText()));
858         HashTable<int>::iterator reactionKeywordIter
859         (
860             reactionKeywordTable_.find(keyword)
861         );
863         if (reactionKeywordIter != reactionKeywordTable_.end())
864         {
865             switch(reactionKeywordIter())
866             {
867                 case unimolecularFallOffReactionType:
868                 {
869                     if (!pDependentSpecieName.size())
870                     {
871                         FatalErrorIn("chemkinReader::lex()")
872                             << "LOW keyword given for a unimolecular fall-off"
873                                " reaction which does not contain a pressure"
874                                " dependent specie" << " on line " << lineNo_
875                             << exit(FatalError);
876                     }
878                     if (rrType == Arrhenius)
879                     {
880                         rrType = unimolecularFallOff;
881                     }
882                     else
883                     {
884                         FatalErrorIn("chemkinReader::lex()")
885                             << "Attempt to set reaction rate type to"
886                                " unimolecularFallOff when it is already set to "
887                             << reactionRateTypeNames[rrType]
888                             << " on line " << lineNo_
889                             << exit(FatalError);
890                     }
892                     if (fofType == unknownFallOffFunctionType)
893                     {
894                         fofType = Lindemann;
895                     }
897                     reactionCoeffsName = reactionRateTypeNames[rrType];
898                     BEGIN(readReactionCoeffs);
899                     break;
900                 }
902                 case chemicallyActivatedBimolecularReactionType:
903                 {
904                     if (!pDependentSpecieName.size())
905                     {
906                         FatalErrorIn("chemkinReader::lex()")
907                             << "HIGH keyword given for a chemically"
908                                " activated bimolecular reaction which does not"
909                                " contain a pressure dependent specie"
910                             << " on line " << lineNo_
911                             << exit(FatalError);
912                     }
914                     if (rrType == Arrhenius)
915                     {
916                         rrType = chemicallyActivatedBimolecular;
917                     }
918                     else
919                     {
920                         FatalErrorIn("chemkinReader::lex()")
921                             << "Attempt to set reaction rate type to"
922                                " chemicallyActivatedBimolecular when it is"
923                                " already set to "
924                             << reactionRateTypeNames[rrType]
925                             << " on line " << lineNo_
926                             << exit(FatalError);
927                     }
929                     if (fofType == unknownFallOffFunctionType)
930                     {
931                         fofType = Lindemann;
932                     }
934                     reactionCoeffsName = reactionRateTypeNames[rrType];
935                     BEGIN(readReactionCoeffs);
936                     break;
937                 }
939                 case TroeReactionType:
940                 {
941                     if (!pDependentSpecieName.size())
942                     {
943                         FatalErrorIn("chemkinReader::lex()")
944                             << "TROE keyword given for a"
945                                " reaction which does not contain a pressure"
946                                " dependent specie" << " on line " << lineNo_
947                             << exit(FatalError);
948                     }
950                     if
951                     (
952                         fofType == unknownFallOffFunctionType
953                      || fofType == Lindemann
954                     )
955                     {
956                         fofType = Troe;
957                     }
958                     else
959                     {
960                         FatalErrorIn("chemkinReader::lex()")
961                             << "Attempt to set fall-off function type to Troe"
962                                " when it is already set to "
963                             << fallOffFunctionNames[fofType]
964                             << " on line " << lineNo_
965                             << exit(FatalError);
966                     }
968                     reactionCoeffsName = fallOffFunctionNames[fofType];
969                     BEGIN(readReactionCoeffs);
970                     break;
971                 }
973                 case SRIReactionType:
974                 {
975                     if (!pDependentSpecieName.size())
976                     {
977                         FatalErrorIn("chemkinReader::lex()")
978                             << "SRI keyword given for a"
979                                " reaction which does not contain a pressure"
980                                " dependent specie" << " on line " << lineNo_
981                             << exit(FatalError);
982                     }
984                     if
985                     (
986                         fofType == unknownFallOffFunctionType
987                      || fofType == Lindemann
988                     )
989                     {
990                         fofType = SRI;
991                     }
992                     else
993                     {
994                         FatalErrorIn("chemkinReader::lex()")
995                             << "Attempt to set fall-off function type to SRI"
996                                " when it is already set to "
997                             << fallOffFunctionNames[fofType]
998                             << " on line " << lineNo_
999                             << exit(FatalError);
1000                     }
1002                     reactionCoeffsName = fallOffFunctionNames[fofType];
1003                     BEGIN(readReactionCoeffs);
1004                     break;
1005                 }
1007                 case LandauTellerReactionType:
1008                 {
1009                     if (pDependentSpecieName.size())
1010                     {
1011                         FatalErrorIn("chemkinReader::lex()")
1012                             << "Landau-Teller reaction rate cannot be used"
1013                                " for the pressure-dependent reaction on line "
1014                             << lineNo_
1015                             << exit(FatalError);
1016                     }
1018                     if (rrType == Arrhenius)
1019                     {
1020                         rrType = LandauTeller;
1021                     }
1022                     else
1023                     {
1024                         FatalErrorIn("chemkinReader::lex()")
1025                             << "Attempt to set reaction rate type to"
1026                                " LandauTeller when it is already set to "
1027                             << reactionRateTypeNames[rrType]
1028                             << " on line " << lineNo_
1029                             << exit(FatalError);
1030                     }
1032                     rrType = LandauTeller;
1033                     reactionCoeffsName = reactionRateTypeNames[rrType];
1034                     BEGIN(readReactionCoeffs);
1035                     break;
1036                 }
1038                 case reverseLandauTellerReactionType:
1039                 {
1040                     if (pDependentSpecieName.size())
1041                     {
1042                         FatalErrorIn("chemkinReader::lex()")
1043                             << "Non-equilibrium Landau-Teller reaction rate"
1044                                " cannot be used"
1045                                " for the pressure-dependent reaction on line "
1046                             << lineNo_
1047                             << exit(FatalError);
1048                     }
1050                     if (rType != nonEquilibriumReversible)
1051                     {
1052                         FatalErrorIn("chemkinReader::lex()")
1053                             << "Reverse reaction Arrhenius coefficients not"
1054                                " given for reverse LandauTeller reaction."
1055                                " Please reorder 'REV' keyword to preceed 'RLT'"
1056                             << " on line " << lineNo_
1057                             << exit(FatalError);
1058                     }
1060                     rrType = LandauTeller;
1061                     reactionCoeffsName =
1062                         word(reactionTypeNames[rType])
1063                       + reactionRateTypeNames[rrType];
1064                     BEGIN(readReactionCoeffs);
1065                     break;
1066                 }
1068                 case JanevReactionType:
1069                 {
1070                     if (rrType == Arrhenius)
1071                     {
1072                         rrType = Janev;
1073                     }
1074                     else
1075                     {
1076                         FatalErrorIn("chemkinReader::lex()")
1077                             << "Attempt to set reaction rate type to"
1078                                " Janev when it is already set to "
1079                             << reactionRateTypeNames[rrType]
1080                             << " on line " << lineNo_
1081                             << exit(FatalError);
1082                     }
1084                     reactionCoeffsName = reactionRateTypeNames[rrType];
1085                     BEGIN(readReactionCoeffs);
1086                     break;
1087                 }
1089                 case powerSeriesReactionRateType:
1090                 {
1091                     if (rrType == Arrhenius)
1092                     {
1093                         rrType = powerSeries;
1094                     }
1095                     else
1096                     {
1097                         FatalErrorIn("chemkinReader::lex()")
1098                             << "Attempt to set reaction rate type to"
1099                                " powerSeries when it is already set to "
1100                             << reactionRateTypeNames[rrType]
1101                             << " on line " << lineNo_
1102                             << exit(FatalError);
1103                     }
1105                     reactionCoeffsName = reactionRateTypeNames[rrType];
1106                     BEGIN(readReactionCoeffs);
1107                     break;
1108                 }
1110                 case radiationActivatedReactionType:
1111                 {
1112                     FatalErrorIn("chemkinReader::lex()")
1113                         << "Radiation activated reaction on line "
1114                         << lineNo_ << "not yet supported"
1115                         << exit(FatalError);
1116                     //reactionCoeffsName = reactionRateTypeNames[rrType];
1117                     BEGIN(readReactionCoeffs);
1118                     break;
1119                 }
1121                 case energyLossReactionType:
1122                 {
1123                     FatalErrorIn("chemkinReader::lex()")
1124                         << "Energy loss in reaction on line "
1125                         << lineNo_ << "not yet supported"
1126                         << exit(FatalError);
1127                     //reactionCoeffsName = reactionRateTypeNames[rrType];
1128                     BEGIN(readReactionCoeffs);
1129                     break;
1130                 }
1132                 case nonEquilibriumReversibleReactionType:
1133                 {
1134                     rType = nonEquilibriumReversible;
1135                     reactionCoeffsName = reactionTypeNames[rType];
1136                     BEGIN(readReactionCoeffs);
1137                     break;
1138                 }
1140                 case speciesOrderForward:
1141                 {
1142                     lrhsPtr = &lhs;
1143                     BEGIN(readReactionOrderSpecie);
1144                     break;
1145                 }
1147                 case speciesOrderReverse:
1148                 {
1149                     lrhsPtr = &rhs;
1150                     BEGIN(readReactionOrderSpecie);
1151                     break;
1152                 }
1154                 case UnitsOfReaction:
1155                 {
1156                     BEGIN(readReactionUnit);
1157                     break;
1158                 }
1160                 default:
1161                 {
1162                     FatalErrorIn("chemkinReader::lex()")
1163                         << "unknown reaction keyword " << keyword
1164                         << " on line " << lineNo_
1165                         << exit(FatalError);
1166                 }
1167             }
1168         }
1169         else
1170         {
1171             HashTable<label>::iterator specieIndexIter
1172             (
1173                 specieIndices_.find(keyword)
1174             );
1176             if (specieIndexIter != specieIndices_.end())
1177             {
1178                 currentThirdBodyIndex = specieIndexIter();
1179             }
1180             else
1181             {
1182                 FatalErrorIn("chemkinReader::lex()")
1183                     << "unknown third-body specie " << keyword
1184                     << " on line " << lineNo_ << nl
1185                     << "Valid species are : " << nl
1186                     << specieIndices_.toc() << endl
1187                     << exit(FatalError);
1188             }
1190             BEGIN(readThirdBodyEfficiency);
1191         }
1192     }
1194 <readSpecieNamePlus>"+" {
1195         currentSpecieName += "+";
1197         HashTable<label>::iterator specieIndexIter
1198         (
1199             specieIndices_.find(currentSpecieName)
1200         );
1202         if (specieIndexIter != specieIndices_.end())
1203         {
1204             if (finishReaction)
1205             {
1206                 addReaction
1207                 (
1208                     lhs,
1209                     rhs,
1210                     thirdBodyEfficiencies,
1211                     rType,
1212                     rrType,
1213                     fofType,
1214                     ArrheniusCoeffs,
1215                     reactionCoeffsTable,
1216                     RRreaction
1217                 );
1218                 finishReaction = false;
1219                 rType = unknownReactionType;
1220                 rrType = Arrhenius;
1221                 fofType = unknownFallOffFunctionType;
1222                 thirdBodyEfficiencies = 1.0;
1223                 pDependentSpecieName = word::null;
1224                 lrhsPtr = &lhs;
1225             }
1227             currentSpecieCoeff.index = specieIndexIter();
1228             lrhsPtr->append(currentSpecieCoeff);
1230             BEGIN(readReactionDelimiter);
1231         }
1232         else
1233         {
1234             FatalErrorIn("chemkinReader::lex()")
1235                 << "unknown specie " << currentSpecieName
1236                 << " on line " << lineNo_ << nl
1237                 << "Valid species are : " << nl
1238                 << specieIndices_.toc() << endl
1239                 << exit(FatalError);
1240         }
1241     }
1243 <readReactionDelimiter>{specieDelimiter} {
1244         currentSpecieCoeff.stoichCoeff = 1.0;
1245         currentSpecieCoeff.exponent = currentSpecieCoeff.stoichCoeff;
1246         BEGIN(readReactionKeyword);
1247     }
1249 <readReactionDelimiter>{irreversibleReactionDelimiter} {
1250         currentSpecieCoeff.stoichCoeff = 1.0;
1251         currentSpecieCoeff.exponent = currentSpecieCoeff.stoichCoeff;
1252         rType = irreversible;
1253         lrhsPtr = &rhs;
1254         BEGIN(readReactionKeyword);
1255     }
1257 <readReactionDelimiter>{reversibleReactionDelimiter} {
1258         currentSpecieCoeff.stoichCoeff = 1.0;
1259         currentSpecieCoeff.exponent = currentSpecieCoeff.stoichCoeff;
1260         rType = reversible;
1261         lrhsPtr = &rhs;
1262         BEGIN(readReactionKeyword);
1263     }
1265 <readReactionDelimiter>& {
1266     }
1268 <readReactionDelimiter>{reactionCoeffs} {
1269         string reactionCoeffsString(YYText());
1270         reactionCoeffsString.replaceAll("d", "e");
1271         reactionCoeffsString.replaceAll("D", "e");
1272         IStringStream reactionCoeffsStream(reactionCoeffsString);
1273         reactionCoeffsStream.lineNumber() = lineNo_;
1275         reactionCoeffsStream
1276             >> ArrheniusCoeffs[0]
1277             >> ArrheniusCoeffs[1]
1278             >> ArrheniusCoeffs[2];
1280         finishReaction = true;
1281         currentSpecieCoeff.stoichCoeff = 1.0;
1282         currentSpecieCoeff.exponent = currentSpecieCoeff.stoichCoeff;
1283         RRreaction = RRreactions;
1285         if (lhsThirdBodyCounter || rhsThirdBodyCounter)
1286         {
1287             if (!lhsThirdBodyCounter || !rhsThirdBodyCounter)
1288             {
1289                 FatalErrorIn("chemkinReader::lex()")
1290                     << "Third body not present on both sides of reaction"
1291                        " on line " << lineNo_
1292                 << exit(FatalError);
1293             }
1295             if (lhsThirdBodyCounter != 1)
1296             {
1297                 FatalErrorIn("chemkinReader::lex()")
1298                     << "More than 1 third body present on l.h.s. side"
1299                        " of reaction on line " << lineNo_
1300                     << exit(FatalError);
1301             }
1303             if (rhsThirdBodyCounter != 1)
1304             {
1305                 FatalErrorIn("chemkinReader::lex()")
1306                     << "More than 1 third body present on r.h.s. side"
1307                        " of reaction on line " << lineNo_
1308                     << exit(FatalError);
1309             }
1311             lhsThirdBodyCounter = 0;
1312             rhsThirdBodyCounter = 0;
1313         }
1315         BEGIN(readReactionKeyword);
1316     }
1319 <readThirdBodyEfficiency>{thirdBodyEfficiency} {
1320         thirdBodyEfficiencies[currentThirdBodyIndex] = stringToScalar(YYText());
1321         BEGIN(readReactionKeyword);
1322     }
1324 <readReactionDelimiter>{startPDependentSpecie} {
1325         BEGIN(readPDependentSpecie);
1326     }
1328 <readPDependentSpecie>{pDependentSpecie} {
1330         word rhsPDependentSpecieName = pDependentSpecieName;
1331         pDependentSpecieName =
1332             foamName(foamSpecieString(YYText()));
1333         pDependentSpecieName =
1334             pDependentSpecieName(0, pDependentSpecieName.size() - 1);
1336         if (rrType == thirdBodyArrhenius)
1337         {
1338             FatalErrorIn("chemkinReader::lex()")
1339                 << "The pressure-dependent third-body '"
1340                 << pDependentSpecieName
1341                 << "' is given in non-pressure-dependent third-body reaction"
1342                 << " on line " << lineNo_
1343                 << exit(FatalError);
1344         }
1346         if (lrhsPtr == &lhs)
1347         {
1348             lhsThirdBodyCounter++;
1349         }
1350         else
1351         {
1352             if (pDependentSpecieName != rhsPDependentSpecieName)
1353             {
1354                 FatalErrorIn("chemkinReader::lex()")
1355                     << "The third-body reactant '"
1356                     << pDependentSpecieName
1357                     << "' is not the same as the third-body product '"
1358                     << rhsPDependentSpecieName
1359                     << "' in pressure-dependent reaction on line " << lineNo_
1360                     << exit(FatalError);
1361             }
1363             rhsThirdBodyCounter++;
1364         }
1366         if (pDependentSpecieName != "M")
1367         {
1368             HashTable<label>::iterator specieIndexIter
1369             (
1370                 specieIndices_.find(pDependentSpecieName)
1371             );
1373             if (specieIndexIter != specieIndices_.end())
1374             {
1375                 thirdBodyEfficiencies = 0.0;
1376                 thirdBodyEfficiencies[specieIndexIter()] = 1.0;
1377             }
1378             else
1379             {
1380                 FatalErrorIn("chemkinReader::lex()")
1381                     << "unknown third-body specie " << pDependentSpecieName
1382                     << " on line " << lineNo_ << nl
1383                     << "Valid species are : " << nl
1384                     << specieIndices_.toc() << endl
1385                     << exit(FatalError);
1386             }
1387         }
1389         BEGIN(readReactionDelimiter);
1390     }
1392 <readReactionCoeffs>{reactionCoeff} {
1393         reactionCoeffs.append(stringToScalar(YYText()));
1394     }
1396 <readReactionCoeffs>{endReactionCoeffs} {
1397         reactionCoeffsTable.insert(reactionCoeffsName, reactionCoeffs.shrink());
1398         reactionCoeffs.clear();
1399         BEGIN(readReactionKeyword);
1400     }
1402 <readTdepSpecie>{specieName} {
1403         word specieName(foamName(foamSpecieString(YYText())));
1404         FatalErrorIn("chemkinReader::lex()")
1405             << "Temperature-dependent reaction on line "
1406             << lineNo_ << "not yet supported"
1407             << exit(FatalError);
1408         BEGIN(readReactionKeyword);
1409     }
1411 <readReactionOrderSpecie>{specieName} {
1412         currentSpecieName =
1413             word(foamName(foamSpecieString(YYText())));
1415         HashTable<label>::iterator specieIndexIter
1416         (
1417             specieIndices_.find(currentSpecieName)
1418         );
1420         if (specieIndexIter != specieIndices_.end())
1421         {
1422             currentSpecieIndex = specieIndexIter();
1423         }
1424         else
1425         {
1426             FatalErrorIn("chemkinReader::lex()")
1427                 << "unknown specie " << currentSpecieName
1428                 << " given in reaction-order specification"
1429                 << " on line " << lineNo_ << nl
1430                 << "Valid species are : " << nl
1431                 << specieIndices_.toc() << endl
1432                 << exit(FatalError);
1433         }
1435         BEGIN(readReactionOrder);
1436     }
1438 <readReactionOrder>{reactionCoeff}{endReactionCoeffs} {
1440         DynamicList<gasReaction::specieCoeffs>& lrhs = *lrhsPtr;
1442         bool found = false;
1444         forAll (lrhs, i)
1445         {
1446             if (lrhs[i].index == currentSpecieIndex)
1447             {
1448                 lrhs[i].exponent = stringToScalar(YYText());
1449                 found = true;
1450                 break;
1451             }
1452         }
1454         if (!found)
1455         {
1456             word side("l.h.s.");
1458             if (lrhsPtr == &rhs)
1459             {
1460                 side = "r.h.s.";
1461             }
1463             FatalErrorIn("chemkinReader::lex()")
1464                 << "Specie " << currentSpecieName
1465                 << " on line " << lineNo_
1466                 << " not present in " << side << " of reaction " << nl << lrhs
1467                 << exit(FatalError);
1468         }
1470         BEGIN(readReactionKeyword);
1471     }
1473 <readReactionUnit>{cal} {
1474         RRreaction = RRcal;
1475     }
1477 <readReactionUnit>{kcal} {
1478         RRreaction = RRcal/1000.0;
1479     }
1481 <readReactionUnit>{joule} {
1482         RRreaction = RRjoule;
1483     }
1485 <readReactionUnit>{kjoule} {
1486         RRreaction = RRjoule/1000.0;
1487     }
1489 <readReactionUnit>{otherReactionsUnit} {
1490     }
1492 <readReactionUnit>{endReactionCoeffs} {
1493         BEGIN(readReactionKeyword);
1494     }
1497  /* ------------------ Ignore remaining space and \n s. --------------------- */
1499 <*>\n      { lineNo_++; }
1501  /* ------ Ignore remaining space and \n s.  Any other characters are errors. */
1503 <*>. {
1504         startError = YYText();
1505         yy_push_state(CHEMKINError);
1506     }
1508 <CHEMKINError>.* {
1509         yy_pop_state();
1510         FatalErrorIn("chemkinReader::lex()")
1511             << "while " << stateNames[YY_START] << " on line " << lineNo_ << nl
1512             << "    expected " << stateExpects[YY_START]
1513             << " but found '" << startError << YYText() << "'"
1514             << exit(FatalError);
1515     }
1518  /*  ------------------------ On EOF terminate. ----------------------------  */
1520 <<EOF>> {
1521         if (finishReaction)
1522         {
1523             addReaction
1524             (
1525                 lhs,
1526                 rhs,
1527                 thirdBodyEfficiencies,
1528                 rType,
1529                 rrType,
1530                 fofType,
1531                 ArrheniusCoeffs,
1532                 reactionCoeffsTable,
1533                 RRreaction
1534             );
1535         }
1536         yyterminate();
1537     }
1540  /* ------------------------------------------------------------------------- *\
1541     ------ End of chemkinLexer.L
1542  \* ------------------------------------------------------------------------- */