Merge branch 'master' of ssh://git.code.sf.net/p/foam-extend/foam-extend-3.2
[foam-extend-3.2.git] / src / thermophysicalModels / reactionThermo / chemistryReaders / chemkinReader / chemkinLexer.L
blobc8206a0b74e44b8c695e1a04facecd2af85bab1f
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | foam-extend: Open Source CFD
4    \\    /   O peration     | Version:     3.2
5     \\  /    A nd           | Web:         http://www.foam-extend.org
6      \\/     M anipulation  | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
8 License
9     This file is part of foam-extend.
11     foam-extend 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 3 of the License, or (at your
14     option) any later version.
16     foam-extend is distributed in the hope that it will be useful, but
17     WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19     General Public License for more details.
21     You should have received a copy of the GNU General Public License
22     along with foam-extend.  If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
28 #undef yyFlexLexer
30 #include "chemkinReader.H"
32 #include "error.H"
33 #include "IStringStream.H"
34 // For EOF only
35 #include <cstdio>
37 // flex input buffer size
38 int Foam::chemkinReader::yyBufSize = YY_BUF_SIZE;
40 // Dummy yyFlexLexer::yylex() to keep the linker happy. It is not called
41 //! @cond dummy
42 int yyFlexLexer::yylex()
44     Foam::FatalErrorIn("yyFlexLexer::yylex()")
45         << "should not have called this function"
46         << abort(Foam::FatalError);
48     return 0;
50 //! @endcond dummy
53 // Dummy yywrap to keep yylex happy at compile time.
54 // It is called by yylex but is not used as the mechanism to change file.
55 // See <<EOF>>
56 //! @cond dummy
57 #if YY_FLEX_MINOR_VERSION < 6 && YY_FLEX_SUBMINOR_VERSION < 34
58 extern "C" int yywrap()
59 #else
60 int yyFlexLexer::yywrap()
61 #endif
63     return 1;
65 //! @endcond dummy
68 Foam::string foamSpecieString(const char* YYText)
70     Foam::string specieString(YYText);
71     // Transforming parentheses is no longer necessary
72     //specieString.replaceAll('(', '<');
73     //specieString.replaceAll(')', '>');
74     return specieString;
78 Foam::word foamName(const char* YYText)
80     Foam::string fn(YYText);
81     Foam::string::stripInvalid<Foam::word>(fn);
82     return fn;
86 Foam::word foamName(const Foam::string& s)
88     Foam::string fn(s);
89     Foam::string::stripInvalid<Foam::word>(fn);
90     return fn;
94  /* ------------------------------------------------------------------------- *\
95    ------ cppLexer::yylex()
96  \* ------------------------------------------------------------------------- */
98 #define YY_DECL int Foam::chemkinReader::lex()
102 one_space             [ \t\f\r]
103 space                 {one_space}*
104 some_space            {one_space}+
105 cspace                ","{space}
107 alpha                 [_A-Za-z]
108 digit                 [0-9]
109 dec_digit             [0-9]
110 octal_digit           [0-7]
111 hex_digit             [0-9a-fA-F]
113 identifier            {alpha}({alpha}|{digit})*
114 integer               {dec_digit}+
115 label                 [1-9]{dec_digit}*
116 zeroLabel             {digit}*
118 word                  ([[:alnum:]]|[[:punct:]])+
119 string                {word}({some_space}{word})*
121 exponent_part         [eEdD][-+]?{digit}+
122 fractional_constant   [-+]?(({digit}*"."{digit}+)|({digit}+"."?))
124 double                (({fractional_constant}{exponent_part}?)|({digit}+{exponent_part}))
127 elements              {space}("ELEMENTS"|"ELEM"){space}
128 species               {space}("SPECIES"|"SPECIE"|"SPEC"){space}
129 thermoAll             {space}"THERMO"{some_space}"ALL"{space}
130 thermo                {space}"THERMO"{space}
131 reactions             {space}("REACTIONS"|"REAC"){space}
132 end                   {space}"END"{space}
134 elementName           {space}([A-Z]|([A-Z][A-Z])){space}
135 startIsotopeMolW      {space}"/"{space}
136 isotopeMolW           {space}{double}{space}"/"{space}
138 specieName            {space}[A-Za-z](([A-Za-z0-9)*+-])|("("[^+]))*{space}
139 nMoles                {space}{double}{space}
141 thermoTemp            .{10}
143 thermoSpecieName      .{18}
144 thermoDate            .{6}
145 thermoFormula         .{20}
146 thermoPhase           S|L|G
147 thermoLowTemp         .{10}
148 thermoHighTemp        .{10}
149 thermoCommonTemp      .{8}
150 thermoFormula2        .{5}
151 thermoCoeff           .{15}
152 thermoLineLabel1      " "1{space}
153 thermoLineLabel2      " "{4}2{space}
154 thermoLineLabel3      " "{4}3{space}
155 thermoLineLabel4      " "{4}4{space}
157 specieDelimiter       {space}"+"{space}
158 reversibleReactionDelimiter {space}("="|"<=>"){space}
159 irreversibleReactionDelimiter {space}"=>"{space}
160 startPDependentSpecie {space}"("{space}"+"{space}
161 pDependentSpecie      {specieName}")"{space}
162 reactionCoeffs        {space}{double}{some_space}{double}{some_space}{double}{space}
163 reactionKeyword       {space}[A-Za-z](([A-Za-z0-9)*-])|("("[^+]))*{space}
164 reactionKeywordSlash  {reactionKeyword}"/"{space}
165 thirdBodyEfficiency   {space}{double}{space}"/"{space}
166 startReactionCoeffs   {space}"/"{space}
167 endReactionCoeffs     {space}"/"{space}
168 reactionCoeff         {space}{double}{space}
170 calPerMol             {space}"CAL/MOLE"{space}
171 kcalPerMol            {space}"KCAL/MOLE"{space}
172 joulePerMol           {space}"JOULES/MOLE"{space}
173 otherReactionsUnit    {space}("KELVINS"|"EVOLTS"|"MOLES"|"MOLECULES"){space}
175 cal                   {space}"CAL"{space}
176 kcal                  {space}"KCAL"{space}
177 joule                 {space}"JOUL"{space}
178 kjoule                {space}"KJOU"{space}
179 otherReactionUnit     {space}("MOLE"|"MOLECULE"|"KELV"|"KELVIN"|"EVOL"|"EVOLTS"){space}
182  /* ------------------------------------------------------------------------- *\
183                       -----  Exclusive start states -----
184  \* ------------------------------------------------------------------------- */
186 %option stack
188 %x readElements
189 %x readIsotopeMolW
190 %x readSpecies
191 %x readThermoAll
192 %x readThermoSpecieName
193 %x readThermoDate
194 %x readThermoFormula
195 %x readThermoPhase
196 %x readThermoTemps
197 %x readThermoFormula2
198 %x readThermoLineLabel1
199 %x readThermoCoeff1
200 %x readThermoLineLabel2
201 %x readThermoCoeff2
202 %x readThermoLineLabel3
203 %x readThermoCoeff3
204 %x readThermoLineLabel4
205 %x readReactionsUnits
206 %x readReactionKeyword
207 %x readSpecieNamePlus
208 %x readReactionDelimiter
209 %x readPDependentSpecie
210 %x readThirdBodyEfficiency
211 %x readReactionCoeffs
212 %x readTdepSpecie
213 %x readReactionOrderSpecie
214 %x readReactionOrder
215 %x readReactionUnit
216 %x CHEMKINError
222 static const char* stateNames[30] =
224     "reading CHEMKIN III file",
225     "reading elements",
226     "reading isotope molecular weight",
227     "reading species",
228     "reading all thermodynamic data temperatures",
229     "reading thermodynamic specie name",
230     "reading thermodynamic data date",
231     "reading thermodynamic data specie formula",
232     "reading thermodynamic data specie phase",
233     "reading thermodynamic data temperatures",
234     "reading thermodynamic data specie formula (supplement)",
235     "reading thermodynamic data line label 1",
236     "reading thermodynamic data coefficient set 1",
237     "reading thermodynamic data line label 2",
238     "reading thermodynamic data coefficient set 2",
239     "reading thermodynamic data line label 3",
240     "reading thermodynamic data coefficient set 3",
241     "reading thermodynamic data line label 4",
242     "reading reaction units",
243     "reading reaction specie/keyword",
244     "reading reaction specie",
245     "reading reaction delimiter",
246     "reading reaction pressure dependent specie",
247     "reading third-body efficiency",
248     "reading reaction coeff",
249     "reading temperature dependent specie name",
250     "reading reaction order specie name",
251     "reading reaction order",
252     "reading reaction unit",
253     "error"
256 static const char* stateExpects[30] =
258     "'ELEMENTS' or 'ELEM', 'SPECIES' or 'SPEC', 'THERMO' or 'THERMO ALL', 'REACTIONS'",
259     "<elementName>, <isotopeName> / or 'END'",
260     "<scalar>/",
261     "<specieName> or 'END'",
262     "<scalar><scalar><scalar> (3F10.0)",
263     "<word> (18A1)",
264     "<word> (6A1)",
265     "<word><label><word><label><word><label><word><label> (4(2A1,I3))",
266     "<char> (A1)",
267     "<scalar><scalar><scalar> (E10.0E10.0E8.0)",
268     "<word><label> (2A1,I3)",
269     "'1' (I1)",
270     "<scalar><scalar><scalar><scalar><scalar> (5(E15.0))",
271     "'2' (I1)",
272     "<scalar><scalar><scalar><scalar><scalar> (5(E15.0))",
273     "'3' (I1)",
274     "<scalar><scalar><scalar><scalar> (4(E15.0))",
275     "'4' (I1)",
276     "'CAL/MOLE', 'KCAL/MOLE', 'JOULES/MOLE', 'KELVINS', 'EVOLTS', 'MOLES' or 'MOLECULES'",
277     "<word> or <label>",
278     "'+'",
279     "'+', '=', '<=>', '=>', '(+<word>', '<scalar> <scalar> <scalar>'",
280     "<word>')'",
281     "<scalar>'/'",
282     "<scalar>",
283     "<word>",
284     "<word>",
285     "<scalar>",
286     "'MOLE', 'MOLECULE', 'CAL', 'KCAL', 'JOUL', 'KJOU', 'KELV', 'KELVIN', 'EVOL' or 'EVOLTS'",
287     ""
290 string startError;
292 static const scalar RRjoule = 8.31451; // J/kg-mol-K
293 static const scalar RRcal = 1.987316;  // cal/g-mol-K
295 scalar RRreactions = RRcal;
296 scalar RRreaction = RRcal;
298 scalar allCommonT = 1000.0;
300 word currentElementName;
301 label currentElementIndex = 0;
303 word currentSpecieName;
304 label currentSpecieIndex = 0;
305 label nSpecieElements = 0;
306 List<specieElement> currentSpecieComposition(5);
308 scalar currentLowT = 0;
309 scalar currentHighT = 0;
310 scalar currentCommonT = 0;
311 gasThermoPhysics::coeffArray highCpCoeffs(scalarList(7));
312 gasThermoPhysics::coeffArray lowCpCoeffs(scalarList(7));
314 gasReaction::specieCoeffs currentSpecieCoeff;
316 DynamicList<gasReaction::specieCoeffs> lhs;
317 DynamicList<gasReaction::specieCoeffs> rhs;
319 scalarList ArrheniusCoeffs(3);
320 DynamicList<scalar> reactionCoeffs;
321 scalarList thirdBodyEfficiencies;
322 label currentThirdBodyIndex = -1;
324 word reactionCoeffsName = word::null;
325 HashTable<scalarList> reactionCoeffsTable;
327 DynamicList<gasReaction::specieCoeffs> *lrhsPtr = &lhs;
329 reactionType rType = unknownReactionType;
330 reactionRateType rrType = Arrhenius;
331 fallOffFunctionType fofType = unknownFallOffFunctionType;
332 word pDependentSpecieName = word::null;
333 label lhsThirdBodyCounter = 0;
334 label rhsThirdBodyCounter = 0;
336 bool finishReaction = false;
340  /* ------------------------------------------------------------------------- *\
341                             ------ Start Lexing ------
342  \* ------------------------------------------------------------------------- */
344  /* ------------------------------------------------------------------------- *\
345     ------ Discard comments being careful to count comments
346  \* ------------------------------------------------------------------------- */
348 <*>{space}"!".* { // Remove one line comments
349     }
351  /* ------------------------------------------------------------------------- *\
352     ------ Read elements
353  \* ------------------------------------------------------------------------- */
355 {elements} {
356         BEGIN(readElements);
357     }
359 <readElements>{elementName} {
360         currentElementName = foamName(YYText());
361         correctElementName(currentElementName);
363         if (!elementIndices_.found(currentElementName))
364         {
365             elementIndices_.insert(currentElementName, currentElementIndex++);
366             elementNames_.append(currentElementName);
367         }
368         else
369         {
370             WarningIn("chemkinReader::lex()")
371                 << "element " << currentElementName
372                 << " already in table." << endl;
373         }
374     }
376 <readElements>{startIsotopeMolW} {
377         BEGIN(readIsotopeMolW);
378     }
380 <readIsotopeMolW>{isotopeMolW} {
381         isotopeAtomicWts_.insert(currentElementName, stringToScalar(YYText()));
382         BEGIN(readElements);
383     }
385 <readElements>{end} {
386         BEGIN(INITIAL);
387     }
389  /* ------------------------------------------------------------------------- *\
390     ------ Read species
391  \* ------------------------------------------------------------------------- */
393 <INITIAL,readElements>{species} {
394         BEGIN(readSpecies);
395     }
397 <readSpecies>{specieName} {
398         word specieName(foamName(foamSpecieString(YYText())));
400         if (specieName == "THERMO")
401         {
402             specieNames_.shrink();
403             speciesTable_ = specieNames_;
404             thirdBodyEfficiencies.setSize(specieNames_.size());
405             thirdBodyEfficiencies = 1.0;
406             BEGIN(readThermoSpecieName);
407         }
408         else if (specieName == "END")
409         {
410             specieNames_.shrink();
411             speciesTable_ = specieNames_;
412             thirdBodyEfficiencies.setSize(specieNames_.size());
413             thirdBodyEfficiencies = 1.0;
414             BEGIN(INITIAL);
415         }
416         else
417         {
418             if (!specieIndices_.found(specieName))
419             {
420                 specieNames_.append(specieName);
421                 specieIndices_.insert(specieName, currentSpecieIndex++);
422             }
423             else
424             {
425                 WarningIn("chemkinReader::lex()")
426                     << "specie " << specieName
427                     << " already in table." << endl;
428             }
429         }
430     }
432  /* ------------------------------------------------------------------------- *\
433     ------ Read thermo
434  \* ------------------------------------------------------------------------- */
436 <INITIAL,readSpecies>{thermo} {
437         BEGIN(readThermoSpecieName);
438     }
440 <INITIAL,readSpecies>{thermoAll} {
441         BEGIN(readThermoAll);
442     }
444 <readThermoAll>{thermoTemp}{thermoTemp}{thermoTemp} {
445         string temperaturesString(YYText());
446         //scalar lowestT(stringToScalar(temperaturesString(0, 10)));
447         allCommonT = stringToScalar(temperaturesString(10, 10));
448         //scalar highestT(stringToScalar(temperaturesString(20, 10)));
449         BEGIN(readThermoSpecieName);
450     }
452 <readThermoSpecieName>{thermoSpecieName} {
453         string specieString(foamSpecieString(YYText()));
454         size_t spacePos = specieString.find(' ');
455         if (spacePos != string::npos)
456         {
457             currentSpecieName = specieString(0, spacePos);
458         }
459         else
460         {
461             currentSpecieName = specieString;
462         }
463         BEGIN(readThermoDate);
464     }
466 <readThermoDate>{thermoDate} {
467         // string thermoDate(YYText());
468         // Date is not currently used
469         BEGIN(readThermoFormula);
470     }
472 <readThermoFormula>{thermoFormula} {
473         string thermoFormula(YYText());
475         nSpecieElements = 0;
476         currentSpecieComposition.setSize(5);
478         for (int i=0; i<4; i++)
479         {
480             word elementName(foamName(thermoFormula(5*i, 2)));
481             label nAtoms = atoi(thermoFormula(5*i + 2, 3).c_str());
483             if (elementName.size() && nAtoms)
484             {
485                 correctElementName(elementName);
486                 currentSpecieComposition[nSpecieElements].elementName =
487                     elementName;
488                 currentSpecieComposition[nSpecieElements++].nAtoms = nAtoms;
489             }
490         }
492         BEGIN(readThermoPhase);
493     }
495 <readThermoPhase>{thermoPhase} {
496         char phaseChar = YYText()[0];
498         switch (phaseChar)
499         {
500             case 'S':
501                 speciePhase_.insert(currentSpecieName, solid);
502             break;
504             case 'L':
505                 speciePhase_.insert(currentSpecieName, liquid);
506             break;
508             case 'G':
509                 speciePhase_.insert(currentSpecieName, gas);
510             break;
511         }
513         BEGIN(readThermoTemps);
514     }
516 <readThermoTemps>{thermoLowTemp}{thermoHighTemp}{thermoCommonTemp} {
517         string temperaturesString(YYText());
518         currentLowT = stringToScalar(temperaturesString(0, 10));
519         currentHighT = stringToScalar(temperaturesString(10, 10));
520         currentCommonT = stringToScalar(temperaturesString(20, 8));
522         if (currentCommonT < SMALL)
523         {
524             currentCommonT = allCommonT;
525         }
527         BEGIN(readThermoFormula2);
528     }
530 <readThermoFormula2>{thermoFormula2} {
531         string thermoFormula(YYText());
532         word elementName(foamName(thermoFormula(0, 2)));
533         label nAtoms = atoi(thermoFormula(2, 3).c_str());
535         if
536         (
537             elementName.size()
538          && elementName.find('0') == string::npos
539          && nAtoms
540         )
541         {
542             correctElementName(elementName);
543             currentSpecieComposition[nSpecieElements].elementName =
544                 elementName;
545             currentSpecieComposition[nSpecieElements++].nAtoms = nAtoms;
546         }
548         currentSpecieComposition.setSize(nSpecieElements);
550         HashTable<List<specieElement> >::iterator specieCompositionIter
551         (
552             specieComposition_.find(currentSpecieName)
553         );
555         if (specieCompositionIter != specieComposition_.end())
556         {
557             specieComposition_.erase(specieCompositionIter);
558         }
560         specieComposition_.insert
561         (
562             currentSpecieName,
563             currentSpecieComposition
564         );
566         BEGIN(readThermoLineLabel1);
567     }
569 <readThermoLineLabel1>{thermoLineLabel1} {
570         BEGIN(readThermoCoeff1);
571     }
573 <readThermoCoeff1>{thermoCoeff}{thermoCoeff}{thermoCoeff}{thermoCoeff}{thermoCoeff} {
574         string thermoCoeffString(YYText());
576         highCpCoeffs[0] = stringToScalar(thermoCoeffString(0, 15));
577         highCpCoeffs[1] = stringToScalar(thermoCoeffString(15, 15));
578         highCpCoeffs[2] = stringToScalar(thermoCoeffString(30, 15));
579         highCpCoeffs[3] = stringToScalar(thermoCoeffString(45, 15));
580         highCpCoeffs[4] = stringToScalar(thermoCoeffString(60, 15));
582         BEGIN(readThermoLineLabel2);
583     }
585 <readThermoLineLabel2>{thermoLineLabel2} {
586         BEGIN(readThermoCoeff2);
587     }
589 <readThermoCoeff2>{thermoCoeff}{thermoCoeff}{thermoCoeff}{thermoCoeff}{thermoCoeff} {
590         string thermoCoeffString(YYText());
592         highCpCoeffs[5] = stringToScalar(thermoCoeffString(0, 15));
593         highCpCoeffs[6] = stringToScalar(thermoCoeffString(15, 15));
595         lowCpCoeffs[0] = stringToScalar(thermoCoeffString(30, 15));
596         lowCpCoeffs[1] = stringToScalar(thermoCoeffString(45, 15));
597         lowCpCoeffs[2] = stringToScalar(thermoCoeffString(60, 15));
599         BEGIN(readThermoLineLabel3);
600     }
602 <readThermoLineLabel3>{thermoLineLabel3} {
603         BEGIN(readThermoCoeff3);
604     }
606 <readThermoCoeff3>{thermoCoeff}{thermoCoeff}{thermoCoeff}{thermoCoeff}{thermoCoeff} {
607         string thermoCoeffString(YYText());
609         lowCpCoeffs[3] = stringToScalar(thermoCoeffString(0, 15));
610         lowCpCoeffs[4] = stringToScalar(thermoCoeffString(15, 15));
611         lowCpCoeffs[5] = stringToScalar(thermoCoeffString(30, 15));
612         lowCpCoeffs[6] = stringToScalar(thermoCoeffString(45, 15));
614         BEGIN(readThermoLineLabel4);
615     }
617 <readThermoLineLabel4>{thermoLineLabel4} {
619         HashPtrTable<gasThermoPhysics>::iterator specieThermoIter
620         (
621             speciesThermo_.find(currentSpecieName)
622         );
624         if (specieThermoIter != speciesThermo_.end())
625         {
626             speciesThermo_.erase(specieThermoIter);
627         }
629         speciesThermo_.insert
630         (
631             currentSpecieName,
632             new gasThermoPhysics
633             (
634                 janafThermo<perfectGas>
635                 (
636                     specie
637                     (
638                         currentSpecieName,
639                         1.0,
640                         molecularWeight(currentSpecieComposition)
641                     ),
642                     currentLowT,
643                     currentHighT,
644                     currentCommonT,
645                     highCpCoeffs,
646                     lowCpCoeffs
647                 ),
648                 1.67212e-6,
649                 170.672
650             )
651         );
653         BEGIN(readThermoSpecieName);
654     }
656 <readThermoSpecieName>{end} {
657         BEGIN(INITIAL);
658     }
660  /* ------------------------------------------------------------------------- *\
661     ------ Read reactions
662  \* ------------------------------------------------------------------------- */
664 <INITIAL,readThermoSpecieName>{reactions} {
665         currentSpecieCoeff.stoichCoeff = 1.0;
666         currentSpecieCoeff.exponent = currentSpecieCoeff.stoichCoeff;
667         BEGIN(readReactionsUnits);
668     }
670 <readReactionsUnits>{calPerMol} {
671         RRreactions = RRcal;
672     }
674 <readReactionsUnits>{kcalPerMol} {
675         RRreactions = RRcal/1000.0;
676     }
678 <readReactionsUnits>{joulePerMol} {
679         RRreactions = RRjoule;
680     }
682 <readReactionsUnits>{otherReactionsUnit} {
683     }
685 <readReactionsUnits>\n {
686         lineNo_++;
687         BEGIN(readReactionKeyword);
688     }
690 <readReactionKeyword>{nMoles} {
691         currentSpecieCoeff.stoichCoeff = atof(YYText());
692         currentSpecieCoeff.exponent = currentSpecieCoeff.stoichCoeff;
693     }
695 <readReactionKeyword>{reactionKeyword} {
697         word keyword(foamName(YYText()));
699         HashTable<int>::iterator reactionKeywordIter
700         (
701             reactionKeywordTable_.find(keyword)
702         );
704         if (reactionKeywordIter != reactionKeywordTable_.end())
705         {
706             switch(reactionKeywordIter())
707             {
708                 case duplicateReactionType:
709                 {
710                     BEGIN(readReactionKeyword);
711                     break;
712                 }
714                 case thirdBodyReactionType:
715                 {
716                     if (rrType != Arrhenius && rrType != thirdBodyArrhenius)
717                     {
718                         FatalErrorIn("chemkinReader::lex()")
719                             << "Attempt to set reaction rate type to"
720                                " thirdBodyArrhenius when it is already set to "
721                             << reactionRateTypeNames[rrType]
722                             << " on line " << lineNo_
723                             << exit(FatalError);
724                     }
726                     if (pDependentSpecieName.size())
727                     {
728                         FatalErrorIn("chemkinReader::lex()")
729                             << "A non-pressure dependent third-body appears in"
730                                " the pressure dependent reaction on line "
731                             << lineNo_
732                             << exit(FatalError);
733                     }
735                     rrType = thirdBodyArrhenius;
737                     if (lrhsPtr == &lhs)
738                     {
739                         lhsThirdBodyCounter++;
740                     }
741                     else
742                     {
743                         rhsThirdBodyCounter++;
744                     }
746                     BEGIN(readReactionDelimiter);
747                     break;
748                 }
750                 case plasmaMomentumTransfer:
751                 {
752                     FatalErrorIn("chemkinReader::lex()")
753                         << "Plasma momentum-transfer in reaction on line "
754                         << lineNo_ << "not yet supported"
755                         << exit(FatalError);
757                     BEGIN(readReactionKeyword);
758                     break;
759                 }
761                 case collisionCrossSection:
762                 {
763                     FatalErrorIn("chemkinReader::lex()")
764                         << "Collision cross-section in reaction on line "
765                         << lineNo_ << "not yet supported"
766                         << exit(FatalError);
768                     BEGIN(readReactionKeyword);
769                     break;
770                 }
772                 case end:
773                 {
774                     BEGIN(INITIAL);
775                     addReaction
776                     (
777                         lhs,
778                         rhs,
779                         thirdBodyEfficiencies,
780                         rType,
781                         rrType,
782                         fofType,
783                         ArrheniusCoeffs,
784                         reactionCoeffsTable,
785                         RRreaction
786                     );
787                     finishReaction = false;
788                     rType = unknownReactionType;
789                     rrType = Arrhenius;
790                     fofType = unknownFallOffFunctionType;
791                     thirdBodyEfficiencies = 1.0;
792                     pDependentSpecieName = word::null;
793                     lrhsPtr = &lhs;
794                     break;
795                 }
797                 default:
798                 {
799                     FatalErrorIn("chemkinReader::lex()")
800                         << "keyword " << keyword
801                         << " should be followed by parameters"
802                         << " on line " << lineNo_
803                         << exit(FatalError);
804                 }
805             }
806         }
807         else
808         {
809             currentSpecieName = foamName(foamSpecieString(YYText()));
811             HashTable<label>::iterator specieIndexIter
812             (
813                 specieIndices_.find(currentSpecieName)
814             );
816             if (specieIndexIter != specieIndices_.end())
817             {
818                 if (finishReaction)
819                 {
820                     addReaction
821                     (
822                         lhs,
823                         rhs,
824                         thirdBodyEfficiencies,
825                         rType,
826                         rrType,
827                         fofType,
828                         ArrheniusCoeffs,
829                         reactionCoeffsTable,
830                         RRreaction
831                     );
832                     finishReaction = false;
833                     rType = unknownReactionType;
834                     rrType = Arrhenius;
835                     fofType = unknownFallOffFunctionType;
836                     thirdBodyEfficiencies = 1.0;
837                     pDependentSpecieName = word::null;
838                     lrhsPtr = &lhs;
839                 }
841                 currentSpecieCoeff.index = specieIndexIter();
842                 lrhsPtr->append(currentSpecieCoeff);
844                 BEGIN(readReactionDelimiter);
845             }
846             else
847             {
848                 BEGIN(readSpecieNamePlus);
849             }
850         }
851     }
853 <readReactionKeyword>{reactionKeywordSlash} {
855         word keyword(foamName(YYText()));
857         HashTable<int>::iterator reactionKeywordIter
858         (
859             reactionKeywordTable_.find(keyword)
860         );
862         if (reactionKeywordIter != reactionKeywordTable_.end())
863         {
864             switch(reactionKeywordIter())
865             {
866                 case unimolecularFallOffReactionType:
867                 {
868                     if (!pDependentSpecieName.size())
869                     {
870                         FatalErrorIn("chemkinReader::lex()")
871                             << "LOW keyword given for a unimolecular fall-off"
872                                " reaction which does not contain a pressure"
873                                " dependent specie" << " on line " << lineNo_
874                             << exit(FatalError);
875                     }
877                     if (rrType == Arrhenius)
878                     {
879                         rrType = unimolecularFallOff;
880                     }
881                     else
882                     {
883                         FatalErrorIn("chemkinReader::lex()")
884                             << "Attempt to set reaction rate type to"
885                                " unimolecularFallOff when it is already set to "
886                             << reactionRateTypeNames[rrType]
887                             << " on line " << lineNo_
888                             << exit(FatalError);
889                     }
891                     if (fofType == unknownFallOffFunctionType)
892                     {
893                         fofType = Lindemann;
894                     }
896                     reactionCoeffsName = reactionRateTypeNames[rrType];
897                     BEGIN(readReactionCoeffs);
898                     break;
899                 }
901                 case chemicallyActivatedBimolecularReactionType:
902                 {
903                     if (!pDependentSpecieName.size())
904                     {
905                         FatalErrorIn("chemkinReader::lex()")
906                             << "HIGH keyword given for a chemically"
907                                " activated bimolecular reaction which does not"
908                                " contain a pressure dependent specie"
909                             << " on line " << lineNo_
910                             << exit(FatalError);
911                     }
913                     if (rrType == Arrhenius)
914                     {
915                         rrType = chemicallyActivatedBimolecular;
916                     }
917                     else
918                     {
919                         FatalErrorIn("chemkinReader::lex()")
920                             << "Attempt to set reaction rate type to"
921                                " chemicallyActivatedBimolecular when it is"
922                                " already set to "
923                             << reactionRateTypeNames[rrType]
924                             << " on line " << lineNo_
925                             << exit(FatalError);
926                     }
928                     if (fofType == unknownFallOffFunctionType)
929                     {
930                         fofType = Lindemann;
931                     }
933                     reactionCoeffsName = reactionRateTypeNames[rrType];
934                     BEGIN(readReactionCoeffs);
935                     break;
936                 }
938                 case TroeReactionType:
939                 {
940                     if (!pDependentSpecieName.size())
941                     {
942                         FatalErrorIn("chemkinReader::lex()")
943                             << "TROE keyword given for a"
944                                " reaction which does not contain a pressure"
945                                " dependent specie" << " on line " << lineNo_
946                             << exit(FatalError);
947                     }
949                     if
950                     (
951                         fofType == unknownFallOffFunctionType
952                      || fofType == Lindemann
953                     )
954                     {
955                         fofType = Troe;
956                     }
957                     else
958                     {
959                         FatalErrorIn("chemkinReader::lex()")
960                             << "Attempt to set fall-off function type to Troe"
961                                " when it is already set to "
962                             << fallOffFunctionNames[fofType]
963                             << " on line " << lineNo_
964                             << exit(FatalError);
965                     }
967                     reactionCoeffsName = fallOffFunctionNames[fofType];
968                     BEGIN(readReactionCoeffs);
969                     break;
970                 }
972                 case SRIReactionType:
973                 {
974                     if (!pDependentSpecieName.size())
975                     {
976                         FatalErrorIn("chemkinReader::lex()")
977                             << "SRI keyword given for a"
978                                " reaction which does not contain a pressure"
979                                " dependent specie" << " on line " << lineNo_
980                             << exit(FatalError);
981                     }
983                     if
984                     (
985                         fofType == unknownFallOffFunctionType
986                      || fofType == Lindemann
987                     )
988                     {
989                         fofType = SRI;
990                     }
991                     else
992                     {
993                         FatalErrorIn("chemkinReader::lex()")
994                             << "Attempt to set fall-off function type to SRI"
995                                " when it is already set to "
996                             << fallOffFunctionNames[fofType]
997                             << " on line " << lineNo_
998                             << exit(FatalError);
999                     }
1001                     reactionCoeffsName = fallOffFunctionNames[fofType];
1002                     BEGIN(readReactionCoeffs);
1003                     break;
1004                 }
1006                 case LandauTellerReactionType:
1007                 {
1008                     if (pDependentSpecieName.size())
1009                     {
1010                         FatalErrorIn("chemkinReader::lex()")
1011                             << "Landau-Teller reaction rate cannot be used"
1012                                " for the pressure-dependent reaction on line "
1013                             << lineNo_
1014                             << exit(FatalError);
1015                     }
1017                     if (rrType == Arrhenius)
1018                     {
1019                         rrType = LandauTeller;
1020                     }
1021                     else
1022                     {
1023                         FatalErrorIn("chemkinReader::lex()")
1024                             << "Attempt to set reaction rate type to"
1025                                " LandauTeller when it is already set to "
1026                             << reactionRateTypeNames[rrType]
1027                             << " on line " << lineNo_
1028                             << exit(FatalError);
1029                     }
1031                     rrType = LandauTeller;
1032                     reactionCoeffsName = reactionRateTypeNames[rrType];
1033                     BEGIN(readReactionCoeffs);
1034                     break;
1035                 }
1037                 case reverseLandauTellerReactionType:
1038                 {
1039                     if (pDependentSpecieName.size())
1040                     {
1041                         FatalErrorIn("chemkinReader::lex()")
1042                             << "Non-equilibrium Landau-Teller reaction rate"
1043                                " cannot be used"
1044                                " for the pressure-dependent reaction on line "
1045                             << lineNo_
1046                             << exit(FatalError);
1047                     }
1049                     if (rType != nonEquilibriumReversible)
1050                     {
1051                         FatalErrorIn("chemkinReader::lex()")
1052                             << "Reverse reaction Arrhenius coefficients not"
1053                                " given for reverse LandauTeller reaction."
1054                                " Please reorder 'REV' keyword to preceed 'RLT'"
1055                             << " on line " << lineNo_
1056                             << exit(FatalError);
1057                     }
1059                     rrType = LandauTeller;
1060                     reactionCoeffsName =
1061                         word(reactionTypeNames[rType])
1062                       + reactionRateTypeNames[rrType];
1063                     BEGIN(readReactionCoeffs);
1064                     break;
1065                 }
1067                 case JanevReactionType:
1068                 {
1069                     if (rrType == Arrhenius)
1070                     {
1071                         rrType = Janev;
1072                     }
1073                     else
1074                     {
1075                         FatalErrorIn("chemkinReader::lex()")
1076                             << "Attempt to set reaction rate type to"
1077                                " Janev when it is already set to "
1078                             << reactionRateTypeNames[rrType]
1079                             << " on line " << lineNo_
1080                             << exit(FatalError);
1081                     }
1083                     reactionCoeffsName = reactionRateTypeNames[rrType];
1084                     BEGIN(readReactionCoeffs);
1085                     break;
1086                 }
1088                 case powerSeriesReactionRateType:
1089                 {
1090                     if (rrType == Arrhenius)
1091                     {
1092                         rrType = powerSeries;
1093                     }
1094                     else
1095                     {
1096                         FatalErrorIn("chemkinReader::lex()")
1097                             << "Attempt to set reaction rate type to"
1098                                " powerSeries when it is already set to "
1099                             << reactionRateTypeNames[rrType]
1100                             << " on line " << lineNo_
1101                             << exit(FatalError);
1102                     }
1104                     reactionCoeffsName = reactionRateTypeNames[rrType];
1105                     BEGIN(readReactionCoeffs);
1106                     break;
1107                 }
1109                 case radiationActivatedReactionType:
1110                 {
1111                     FatalErrorIn("chemkinReader::lex()")
1112                         << "Radiation activated reaction on line "
1113                         << lineNo_ << "not yet supported"
1114                         << exit(FatalError);
1115                     //reactionCoeffsName = reactionRateTypeNames[rrType];
1116                     BEGIN(readReactionCoeffs);
1117                     break;
1118                 }
1120                 case energyLossReactionType:
1121                 {
1122                     FatalErrorIn("chemkinReader::lex()")
1123                         << "Energy loss in reaction on line "
1124                         << lineNo_ << "not yet supported"
1125                         << exit(FatalError);
1126                     //reactionCoeffsName = reactionRateTypeNames[rrType];
1127                     BEGIN(readReactionCoeffs);
1128                     break;
1129                 }
1131                 case nonEquilibriumReversibleReactionType:
1132                 {
1133                     rType = nonEquilibriumReversible;
1134                     reactionCoeffsName = reactionTypeNames[rType];
1135                     BEGIN(readReactionCoeffs);
1136                     break;
1137                 }
1139                 case speciesOrderForward:
1140                 {
1141                     lrhsPtr = &lhs;
1142                     BEGIN(readReactionOrderSpecie);
1143                     break;
1144                 }
1146                 case speciesOrderReverse:
1147                 {
1148                     lrhsPtr = &rhs;
1149                     BEGIN(readReactionOrderSpecie);
1150                     break;
1151                 }
1153                 case UnitsOfReaction:
1154                 {
1155                     BEGIN(readReactionUnit);
1156                     break;
1157                 }
1159                 default:
1160                 {
1161                     FatalErrorIn("chemkinReader::lex()")
1162                         << "unknown reaction keyword " << keyword
1163                         << " on line " << lineNo_
1164                         << exit(FatalError);
1165                 }
1166             }
1167         }
1168         else
1169         {
1170             HashTable<label>::iterator specieIndexIter
1171             (
1172                 specieIndices_.find(keyword)
1173             );
1175             if (specieIndexIter != specieIndices_.end())
1176             {
1177                 currentThirdBodyIndex = specieIndexIter();
1178             }
1179             else
1180             {
1181                 FatalErrorIn("chemkinReader::lex()")
1182                     << "unknown third-body specie " << keyword
1183                     << " on line " << lineNo_ << nl
1184                     << "Valid species are : " << nl
1185                     << specieIndices_.toc() << endl
1186                     << exit(FatalError);
1187             }
1189             BEGIN(readThirdBodyEfficiency);
1190         }
1191     }
1193 <readSpecieNamePlus>"+" {
1194         currentSpecieName += "+";
1196         HashTable<label>::iterator specieIndexIter
1197         (
1198             specieIndices_.find(currentSpecieName)
1199         );
1201         if (specieIndexIter != specieIndices_.end())
1202         {
1203             if (finishReaction)
1204             {
1205                 addReaction
1206                 (
1207                     lhs,
1208                     rhs,
1209                     thirdBodyEfficiencies,
1210                     rType,
1211                     rrType,
1212                     fofType,
1213                     ArrheniusCoeffs,
1214                     reactionCoeffsTable,
1215                     RRreaction
1216                 );
1217                 finishReaction = false;
1218                 rType = unknownReactionType;
1219                 rrType = Arrhenius;
1220                 fofType = unknownFallOffFunctionType;
1221                 thirdBodyEfficiencies = 1.0;
1222                 pDependentSpecieName = word::null;
1223                 lrhsPtr = &lhs;
1224             }
1226             currentSpecieCoeff.index = specieIndexIter();
1227             lrhsPtr->append(currentSpecieCoeff);
1229             BEGIN(readReactionDelimiter);
1230         }
1231         else
1232         {
1233             FatalErrorIn("chemkinReader::lex()")
1234                 << "unknown specie " << currentSpecieName
1235                 << " on line " << lineNo_ << nl
1236                 << "Valid species are : " << nl
1237                 << specieIndices_.toc() << endl
1238                 << exit(FatalError);
1239         }
1240     }
1242 <readReactionDelimiter>{specieDelimiter} {
1243         currentSpecieCoeff.stoichCoeff = 1.0;
1244         currentSpecieCoeff.exponent = currentSpecieCoeff.stoichCoeff;
1245         BEGIN(readReactionKeyword);
1246     }
1248 <readReactionDelimiter>{irreversibleReactionDelimiter} {
1249         currentSpecieCoeff.stoichCoeff = 1.0;
1250         currentSpecieCoeff.exponent = currentSpecieCoeff.stoichCoeff;
1251         rType = irreversible;
1252         lrhsPtr = &rhs;
1253         BEGIN(readReactionKeyword);
1254     }
1256 <readReactionDelimiter>{reversibleReactionDelimiter} {
1257         currentSpecieCoeff.stoichCoeff = 1.0;
1258         currentSpecieCoeff.exponent = currentSpecieCoeff.stoichCoeff;
1259         rType = reversible;
1260         lrhsPtr = &rhs;
1261         BEGIN(readReactionKeyword);
1262     }
1264 <readReactionDelimiter>& {
1265     }
1267 <readReactionDelimiter>{reactionCoeffs} {
1268         string reactionCoeffsString(YYText());
1269         reactionCoeffsString.replaceAll("d", "e");
1270         reactionCoeffsString.replaceAll("D", "e");
1271         IStringStream reactionCoeffsStream(reactionCoeffsString);
1272         reactionCoeffsStream.lineNumber() = lineNo_;
1274         reactionCoeffsStream
1275             >> ArrheniusCoeffs[0]
1276             >> ArrheniusCoeffs[1]
1277             >> ArrheniusCoeffs[2];
1279         finishReaction = true;
1280         currentSpecieCoeff.stoichCoeff = 1.0;
1281         currentSpecieCoeff.exponent = currentSpecieCoeff.stoichCoeff;
1282         RRreaction = RRreactions;
1284         if (lhsThirdBodyCounter || rhsThirdBodyCounter)
1285         {
1286             if (!lhsThirdBodyCounter || !rhsThirdBodyCounter)
1287             {
1288                 FatalErrorIn("chemkinReader::lex()")
1289                     << "Third body not present on both sides of reaction"
1290                        " on line " << lineNo_
1291                 << exit(FatalError);
1292             }
1294             if (lhsThirdBodyCounter != 1)
1295             {
1296                 FatalErrorIn("chemkinReader::lex()")
1297                     << "More than 1 third body present on l.h.s. side"
1298                        " of reaction on line " << lineNo_
1299                     << exit(FatalError);
1300             }
1302             if (rhsThirdBodyCounter != 1)
1303             {
1304                 FatalErrorIn("chemkinReader::lex()")
1305                     << "More than 1 third body present on r.h.s. side"
1306                        " of reaction on line " << lineNo_
1307                     << exit(FatalError);
1308             }
1310             lhsThirdBodyCounter = 0;
1311             rhsThirdBodyCounter = 0;
1312         }
1314         BEGIN(readReactionKeyword);
1315     }
1318 <readThirdBodyEfficiency>{thirdBodyEfficiency} {
1319         thirdBodyEfficiencies[currentThirdBodyIndex] = stringToScalar(YYText());
1320         BEGIN(readReactionKeyword);
1321     }
1323 <readReactionDelimiter>{startPDependentSpecie} {
1324         BEGIN(readPDependentSpecie);
1325     }
1327 <readPDependentSpecie>{pDependentSpecie} {
1329         word rhsPDependentSpecieName = pDependentSpecieName;
1330         pDependentSpecieName =
1331             foamName(foamSpecieString(YYText()));
1332         pDependentSpecieName =
1333             pDependentSpecieName(0, pDependentSpecieName.size() - 1);
1335         if (rrType == thirdBodyArrhenius)
1336         {
1337             FatalErrorIn("chemkinReader::lex()")
1338                 << "The pressure-dependent third-body '"
1339                 << pDependentSpecieName
1340                 << "' is given in non-pressure-dependent third-body reaction"
1341                 << " on line " << lineNo_
1342                 << exit(FatalError);
1343         }
1345         if (lrhsPtr == &lhs)
1346         {
1347             lhsThirdBodyCounter++;
1348         }
1349         else
1350         {
1351             if (pDependentSpecieName != rhsPDependentSpecieName)
1352             {
1353                 FatalErrorIn("chemkinReader::lex()")
1354                     << "The third-body reactant '"
1355                     << pDependentSpecieName
1356                     << "' is not the same as the third-body product '"
1357                     << rhsPDependentSpecieName
1358                     << "' in pressure-dependent reaction on line " << lineNo_
1359                     << exit(FatalError);
1360             }
1362             rhsThirdBodyCounter++;
1363         }
1365         if (pDependentSpecieName != "M")
1366         {
1367             HashTable<label>::iterator specieIndexIter
1368             (
1369                 specieIndices_.find(pDependentSpecieName)
1370             );
1372             if (specieIndexIter != specieIndices_.end())
1373             {
1374                 thirdBodyEfficiencies = 0.0;
1375                 thirdBodyEfficiencies[specieIndexIter()] = 1.0;
1376             }
1377             else
1378             {
1379                 FatalErrorIn("chemkinReader::lex()")
1380                     << "unknown third-body specie " << pDependentSpecieName
1381                     << " on line " << lineNo_ << nl
1382                     << "Valid species are : " << nl
1383                     << specieIndices_.toc() << endl
1384                     << exit(FatalError);
1385             }
1386         }
1388         BEGIN(readReactionDelimiter);
1389     }
1391 <readReactionCoeffs>{reactionCoeff} {
1392         reactionCoeffs.append(stringToScalar(YYText()));
1393     }
1395 <readReactionCoeffs>{endReactionCoeffs} {
1396         reactionCoeffsTable.insert(reactionCoeffsName, reactionCoeffs.shrink());
1397         reactionCoeffs.clear();
1398         BEGIN(readReactionKeyword);
1399     }
1401 <readTdepSpecie>{specieName} {
1402         word specieName(foamName(foamSpecieString(YYText())));
1403         FatalErrorIn("chemkinReader::lex()")
1404             << "Temperature-dependent reaction on line "
1405             << lineNo_ << "not yet supported"
1406             << exit(FatalError);
1407         BEGIN(readReactionKeyword);
1408     }
1410 <readReactionOrderSpecie>{specieName} {
1411         currentSpecieName =
1412             word(foamName(foamSpecieString(YYText())));
1414         HashTable<label>::iterator specieIndexIter
1415         (
1416             specieIndices_.find(currentSpecieName)
1417         );
1419         if (specieIndexIter != specieIndices_.end())
1420         {
1421             currentSpecieIndex = specieIndexIter();
1422         }
1423         else
1424         {
1425             FatalErrorIn("chemkinReader::lex()")
1426                 << "unknown specie " << currentSpecieName
1427                 << " given in reaction-order specification"
1428                 << " on line " << lineNo_ << nl
1429                 << "Valid species are : " << nl
1430                 << specieIndices_.toc() << endl
1431                 << exit(FatalError);
1432         }
1434         BEGIN(readReactionOrder);
1435     }
1437 <readReactionOrder>{reactionCoeff}{endReactionCoeffs} {
1439         DynamicList<gasReaction::specieCoeffs>& lrhs = *lrhsPtr;
1441         bool found = false;
1443         forAll (lrhs, i)
1444         {
1445             if (lrhs[i].index == currentSpecieIndex)
1446             {
1447                 lrhs[i].exponent = stringToScalar(YYText());
1448                 found = true;
1449                 break;
1450             }
1451         }
1453         if (!found)
1454         {
1455             word side("l.h.s.");
1457             if (lrhsPtr == &rhs)
1458             {
1459                 side = "r.h.s.";
1460             }
1462             FatalErrorIn("chemkinReader::lex()")
1463                 << "Specie " << currentSpecieName
1464                 << " on line " << lineNo_
1465                 << " not present in " << side << " of reaction " << nl << lrhs
1466                 << exit(FatalError);
1467         }
1469         BEGIN(readReactionKeyword);
1470     }
1472 <readReactionUnit>{cal} {
1473         RRreaction = RRcal;
1474     }
1476 <readReactionUnit>{kcal} {
1477         RRreaction = RRcal/1000.0;
1478     }
1480 <readReactionUnit>{joule} {
1481         RRreaction = RRjoule;
1482     }
1484 <readReactionUnit>{kjoule} {
1485         RRreaction = RRjoule/1000.0;
1486     }
1488 <readReactionUnit>{otherReactionsUnit} {
1489     }
1491 <readReactionUnit>{endReactionCoeffs} {
1492         BEGIN(readReactionKeyword);
1493     }
1496  /* ------------------ Ignore remaining space and \n s. --------------------- */
1498 <*>\n      { lineNo_++; }
1500  /* ------ Ignore remaining space and \n s.  Any other characters are errors. */
1502 <*>. {
1503         startError = YYText();
1504         yy_push_state(CHEMKINError);
1505     }
1507 <CHEMKINError>.* {
1508         yy_pop_state();
1509         FatalErrorIn("chemkinReader::lex()")
1510             << "while " << stateNames[YY_START] << " on line " << lineNo_ << nl
1511             << "    expected " << stateExpects[YY_START]
1512             << " but found '" << startError << YYText() << "'"
1513             << exit(FatalError);
1514     }
1517  /*  ------------------------ On EOF terminate. ----------------------------  */
1519 <<EOF>> {
1520         if (finishReaction)
1521         {
1522             addReaction
1523             (
1524                 lhs,
1525                 rhs,
1526                 thirdBodyEfficiencies,
1527                 rType,
1528                 rrType,
1529                 fofType,
1530                 ArrheniusCoeffs,
1531                 reactionCoeffsTable,
1532                 RRreaction
1533             );
1534         }
1535         yyterminate();
1536     }
1539  /* ------------------------------------------------------------------------- *\
1540     ------ End of chemkinLexer.L
1541  \* ------------------------------------------------------------------------- */