intersection with triangle plane for miss
[OpenFOAM-1.5.x.git] / src / thermophysicalModels / combustion / chemistryReaders / chemkinReader / chemkinLexer.L
blobbfbb4de1e6f8aad3d3db14519a950d27c0d0b746
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 1991-2008 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"
36 // flex input buffer size
37 int Foam::chemkinReader::yyBufSize = YY_BUF_SIZE;
39 // Dummy yyFlexLexer::yylex() to keep the linker happy. It is not called
40 //! @cond dummy
41 int yyFlexLexer::yylex()
43     Foam::FatalErrorIn("yyFlexLexer::yylex()")
44         << "should not have called this function"
45         << abort(Foam::FatalError);
47     return 0;
49 //! @endcond dummy
52 // Dummy yywrap to keep yylex happy at compile time.
53 // It is called by yylex but is not used as the mechanism to change file.
54 // See <<EOF>>
55 //! @cond dummy
56 #if YY_FLEX_SUBMINOR_VERSION < 34
57 extern "C" int yywrap()
58 #else
59 int yyFlexLexer::yywrap()
60 #endif
62     return 1;
64 //! @endcond dummy
67 Foam::string foamSpecieString(const char* YYText)
69     Foam::string specieString(YYText);
70     specieString.replaceAll('(', '<');
71     specieString.replaceAll(')', '>');
72     return specieString;
76 Foam::word foamName(const char* YYText)
78     Foam::string fn(YYText);
79     Foam::string::stripInvalid<Foam::word>(fn);
80     return fn;
84 Foam::word foamName(const Foam::string& s)
86     Foam::string fn(s);
87     Foam::string::stripInvalid<Foam::word>(fn);
88     return fn;
92  /* ------------------------------------------------------------------------- *\
93    ------ cppLexer::yylex()
94  \* ------------------------------------------------------------------------- */
96 #define YY_DECL int Foam::chemkinReader::lex()
100 one_space             [ \t\f\r]
101 space                 {one_space}*
102 some_space            {one_space}+
103 cspace                ","{space}
105 alpha                 [_A-Za-z]
106 digit                 [0-9]
107 dec_digit             [0-9]
108 octal_digit           [0-7]
109 hex_digit             [0-9a-fA-F]
111 identifier            {alpha}({alpha}|{digit})*
112 integer               {dec_digit}+
113 label                 [1-9]{dec_digit}*
114 zeroLabel             {digit}*
116 word                  ([[:alnum:]]|[[:punct:]])+
117 string                {word}({some_space}{word})*
119 exponent_part         [eEdD][-+]?{digit}+
120 fractional_constant   [-+]?(({digit}*"."{digit}+)|({digit}+"."?))
122 double                (({fractional_constant}{exponent_part}?)|({digit}+{exponent_part}))
125 elements              {space}("ELEMENTS"|"ELEM"){space}
126 species               {space}("SPECIES"|"SPECIE"|"SPEC"){space}
127 thermoAll             {space}"THERMO"{some_space}"ALL"{space}
128 thermo                {space}"THERMO"{space}
129 reactions             {space}("REACTIONS"|"REAC"){space}
130 end                   {space}"END"{space}
132 elementName           {space}([A-Z]|([A-Z][A-Z])){space}
133 startIsotopeMolW      {space}"/"{space}
134 isotopeMolW           {space}{double}{space}"/"{space}
136 specieName            {space}[A-Za-z](([A-Za-z0-9)*+-])|("("[^+]))*{space}
137 nMoles                {space}{double}{space}
139 thermoTemp            .{10}
141 thermoSpecieName      .{18}
142 thermoDate            .{6}
143 thermoFormula         .{20}
144 thermoPhase           S|L|G
145 thermoLowTemp         .{10}
146 thermoHighTemp        .{10}
147 thermoCommonTemp      .{8}
148 thermoFormula2        .{5}
149 thermoCoeff           .{15}
150 thermoLineLabel1      " "1{space}
151 thermoLineLabel2      " "{4}2{space}
152 thermoLineLabel3      " "{4}3{space}
153 thermoLineLabel4      " "{4}4{space}
155 specieDelimiter       {space}"+"{space}
156 reversibleReactionDelimiter {space}("="|"<=>"){space}
157 irreversibleReactionDelimiter {space}"=>"{space}
158 startPDependentSpecie {space}"("{space}"+"{space}
159 pDependentSpecie      {specieName}")"{space}
160 reactionCoeffs        {space}{double}{some_space}{double}{some_space}{double}{space}
161 reactionKeyword       {space}[A-Za-z](([A-Za-z0-9)*-])|("("[^+]))*{space}
162 reactionKeywordSlash  {reactionKeyword}"/"{space}
163 thirdBodyEfficiency   {space}{double}{space}"/"{space}
164 startReactionCoeffs   {space}"/"{space}
165 endReactionCoeffs     {space}"/"{space}
166 reactionCoeff         {space}{double}{space}
168 calPerMol             {space}"CAL/MOLE"{space}
169 kcalPerMol            {space}"KCAL/MOLE"{space}
170 joulePerMol           {space}"JOULES/MOLE"{space}
171 otherReactionsUnit    {space}("KELVINS"|"EVOLTS"|"MOLES"|"MOLECULES"){space}
173 cal                   {space}"CAL"{space}
174 kcal                  {space}"KCAL"{space}
175 joule                 {space}"JOUL"{space}
176 kjoule                {space}"KJOU"{space}
177 otherReactionUnit     {space}("MOLE"|"MOLECULE"|"KELV"|"KELVIN"|"EVOL"|"EVOLTS"){space}
180  /* ------------------------------------------------------------------------- *\
181                       -----  Exclusive start states -----
182  \* ------------------------------------------------------------------------- */
184 %option stack
186 %x readElements
187 %x readIsotopeMolW
188 %x readSpecies
189 %x readThermoAll
190 %x readThermoSpecieName
191 %x readThermoDate
192 %x readThermoFormula
193 %x readThermoPhase
194 %x readThermoTemps
195 %x readThermoFormula2
196 %x readThermoLineLabel1
197 %x readThermoCoeff1
198 %x readThermoLineLabel2
199 %x readThermoCoeff2
200 %x readThermoLineLabel3
201 %x readThermoCoeff3
202 %x readThermoLineLabel4
203 %x readReactionsUnits
204 %x readReactionKeyword
205 %x readSpecieNamePlus
206 %x readReactionDelimiter
207 %x readPDependentSpecie
208 %x readThirdBodyEfficiency
209 %x readReactionCoeffs
210 %x readTdepSpecie
211 %x readReactionOrderSpecie
212 %x readReactionOrder
213 %x readReactionUnit
214 %x CHEMKINError
220 static const char* stateNames[30] =
222     "reading CHEMKIN III file",
223     "reading elements",
224     "reading isotope molecular weight",
225     "reading species",
226     "reading all thermodynamic data temperatures",
227     "reading thermodynamic specie name",
228     "reading thermodynamic data date",
229     "reading thermodynamic data specie formula",
230     "reading thermodynamic data specie phase",
231     "reading thermodynamic data temperatures",
232     "reading thermodynamic data specie formula (supplement)",
233     "reading thermodynamic data line label 1",
234     "reading thermodynamic data coefficient set 1",
235     "reading thermodynamic data line label 2",
236     "reading thermodynamic data coefficient set 2",
237     "reading thermodynamic data line label 3",
238     "reading thermodynamic data coefficient set 3",
239     "reading thermodynamic data line label 4",
240     "reading reaction units",
241     "reading reaction specie/keyword",
242     "reading reaction specie",
243     "reading reaction delimiter",
244     "reading reaction pressure dependent specie",
245     "reading third-body efficiency",
246     "reading reaction coeff",
247     "reading temperature dependent specie name",
248     "reading reaction order specie name",
249     "reading reaction order",
250     "reading reaction unit",
251     "error"
254 static const char* stateExpects[30] =
256     "'ELEMENTS' or 'ELEM', 'SPECIES' or 'SPEC', 'THERMO' or 'THERMO ALL', 'REACTIONS'",
257     "<elementName>, <isotopeName> / or 'END'",
258     "<scalar>/",
259     "<specieName> or 'END'",
260     "<scalar><scalar><scalar> (3F10.0)",
261     "<word> (18A1)",
262     "<word> (6A1)",
263     "<word><label><word><label><word><label><word><label> (4(2A1,I3))",
264     "<char> (A1)",
265     "<scalar><scalar><scalar> (E10.0E10.0E8.0)",
266     "<word><label> (2A1,I3)",
267     "'1' (I1)",
268     "<scalar><scalar><scalar><scalar><scalar> (5(E15.0))",
269     "'2' (I1)",
270     "<scalar><scalar><scalar><scalar><scalar> (5(E15.0))",
271     "'3' (I1)",
272     "<scalar><scalar><scalar><scalar> (4(E15.0))",
273     "'4' (I1)",
274     "'CAL/MOLE', 'KCAL/MOLE', 'JOULES/MOLE', 'KELVINS', 'EVOLTS', 'MOLES' or 'MOLECULES'",
275     "<word> or <label>",
276     "'+'",
277     "'+', '=', '<=>', '=>', '(+<word>', '<scalar> <scalar> <scalar>'",
278     "<word>')'",
279     "<scalar>'/'",
280     "<scalar>",
281     "<word>",
282     "<word>",
283     "<scalar>",
284     "'MOLE', 'MOLECULE', 'CAL', 'KCAL', 'JOUL', 'KJOU', 'KELV', 'KELVIN', 'EVOL' or 'EVOLTS'",
285     ""
288 string startError;
290 static const scalar RRjoule = 8.31451; // J/kg-mol-K
291 static const scalar RRcal = 1.987316;  // cal/g-mol-K
293 scalar RRreactions = RRcal;
294 scalar RRreaction = RRcal;
296 scalar allCommonT = 1000.0;
298 word currentElementName;
299 label currentElementIndex = 0;
301 word currentSpecieName;
302 label currentSpecieIndex = 0;
303 label nSpecieElements = 0;
304 List<specieElement> currentSpecieComposition(5);
306 scalar currentLowT = 0;
307 scalar currentHighT = 0;
308 scalar currentCommonT = 0;
309 reactionThermo::coeffArray highCpCoeffs;
310 reactionThermo::coeffArray lowCpCoeffs;
312 reaction::specieCoeffs currentSpecieCoeff;
314 DynamicList<reaction::specieCoeffs> lhs;
315 DynamicList<reaction::specieCoeffs> rhs;
317 scalarList ArrheniusCoeffs(3);
318 DynamicList<scalar> reactionCoeffs;
319 scalarList thirdBodyEfficiencies;
320 label currentThirdBodyIndex = -1;
322 word reactionCoeffsName = word::null;
323 HashTable<scalarList> reactionCoeffsTable;
325 DynamicList<reaction::specieCoeffs> *lrhsPtr = &lhs;
327 reactionType rType = unknownReactionType;
328 reactionRateType rrType = Arrhenius;
329 fallOffFunctionType fofType = unknownFallOffFunctionType;
330 word pDependentSpecieName = word::null;
331 label lhsThirdBodyCounter = 0;
332 label rhsThirdBodyCounter = 0;
334 bool finishReaction = false;
338  /* ------------------------------------------------------------------------- *\
339                             ------ Start Lexing ------
340  \* ------------------------------------------------------------------------- */
342  /* ------------------------------------------------------------------------- *\
343     ------ Discard comments being careful to count comments
344  \* ------------------------------------------------------------------------- */
346 <*>{space}"!".* { // Remove one line comments
347     }
349  /* ------------------------------------------------------------------------- *\
350     ------ Read elements
351  \* ------------------------------------------------------------------------- */
353 {elements} {
354         BEGIN(readElements);
355     }
357 <readElements>{elementName} {
358         currentElementName = foamName(YYText());
359         correctElementName(currentElementName);
361         if (!elementIndices_.found(currentElementName))
362         {
363             elementIndices_.insert(currentElementName, currentElementIndex++);
364             elementNames_.append(currentElementName);
365         }
366         else
367         {
368             WarningIn("chemkinReader::lex()")
369                 << "element " << currentElementName
370                 << " already in table." << endl;
371         }
372     }
374 <readElements>{startIsotopeMolW} {
375         BEGIN(readIsotopeMolW);
376     }
378 <readIsotopeMolW>{isotopeMolW} {
379         isotopeAtomicWts_.insert(currentElementName, stringToScalar(YYText()));
380         BEGIN(readElements);
381     }
383 <readElements>{end} {
384         BEGIN(INITIAL);
385     }
387  /* ------------------------------------------------------------------------- *\
388     ------ Read species
389  \* ------------------------------------------------------------------------- */
391 <INITIAL,readElements>{species} {
392         BEGIN(readSpecies);
393     }
395 <readSpecies>{specieName} {
396         word specieName(foamName(foamSpecieString(YYText())));
398         if (specieName == "THERMO")
399         {
400             specieNames_.shrink();
401             speciesTable_ = specieNames_;
402             thirdBodyEfficiencies.setSize(specieNames_.size());
403             thirdBodyEfficiencies = 1.0;
404             BEGIN(readThermoSpecieName);
405         }
406         else if (specieName == "END")
407         {
408             specieNames_.shrink();
409             speciesTable_ = specieNames_;
410             thirdBodyEfficiencies.setSize(specieNames_.size());
411             thirdBodyEfficiencies = 1.0;
412             BEGIN(INITIAL);
413         }
414         else
415         {
416             if (!specieIndices_.found(specieName))
417             {
418                 specieNames_.append(specieName);
419                 specieIndices_.insert(specieName, currentSpecieIndex++);
420             }
421             else
422             {
423                 WarningIn("chemkinReader::lex()")
424                     << "specie " << specieName
425                     << " already in table." << endl;
426             }
427         }
428     }
430  /* ------------------------------------------------------------------------- *\
431     ------ Read thermo
432  \* ------------------------------------------------------------------------- */
434 <INITIAL,readSpecies>{thermo} {
435         BEGIN(readThermoSpecieName);
436     }
438 <INITIAL,readSpecies>{thermoAll} {
439         BEGIN(readThermoAll);
440     }
442 <readThermoAll>{thermoTemp}{thermoTemp}{thermoTemp} {
443         string temperaturesString(YYText());
444         //scalar lowestT(stringToScalar(temperaturesString(0, 10)));
445         allCommonT = stringToScalar(temperaturesString(10, 10));
446         //scalar highestT(stringToScalar(temperaturesString(20, 10)));
447         BEGIN(readThermoSpecieName);
448     }
450 <readThermoSpecieName>{thermoSpecieName} {
451         string specieString(foamSpecieString(YYText()));
452         size_t spacePos = specieString.find(' ');
453         if (spacePos != string::npos)
454         {
455             currentSpecieName = specieString(0, spacePos);
456         }
457         else
458         {
459             currentSpecieName = specieString;
460         }
461         BEGIN(readThermoDate);
462     }
464 <readThermoDate>{thermoDate} {
465         // string thermoDate(YYText());
466         // Date is not currently used
467         BEGIN(readThermoFormula);
468     }
470 <readThermoFormula>{thermoFormula} {
471         string thermoFormula(YYText());
473         nSpecieElements = 0;
474         currentSpecieComposition.setSize(5);
476         for (int i=0; i<4; i++)
477         {
478             word elementName(foamName(thermoFormula(5*i, 2)));
479             label nAtoms = atoi(thermoFormula(5*i + 2, 3).c_str());
481             if (elementName.size() && nAtoms)
482             {
483                 correctElementName(elementName);
484                 currentSpecieComposition[nSpecieElements].elementName =
485                     elementName;
486                 currentSpecieComposition[nSpecieElements++].nAtoms = nAtoms;
487             }
488         }
490         BEGIN(readThermoPhase);
491     }
493 <readThermoPhase>{thermoPhase} {
494         char phaseChar = YYText()[0];
496         switch (phaseChar)
497         {
498             case 'S':
499                 speciePhase_.insert(currentSpecieName, solid);
500             break;
502             case 'L':
503                 speciePhase_.insert(currentSpecieName, liquid);
504             break;
506             case 'G':
507                 speciePhase_.insert(currentSpecieName, gas);
508             break;
509         }
511         BEGIN(readThermoTemps);
512     }
514 <readThermoTemps>{thermoLowTemp}{thermoHighTemp}{thermoCommonTemp} {
515         string temperaturesString(YYText());
516         currentLowT = stringToScalar(temperaturesString(0, 10));
517         currentHighT = stringToScalar(temperaturesString(10, 10));
518         currentCommonT = stringToScalar(temperaturesString(20, 8));
520         if (currentCommonT < SMALL)
521         {
522             currentCommonT = allCommonT;
523         }
525         BEGIN(readThermoFormula2);
526     }
528 <readThermoFormula2>{thermoFormula2} {
529         string thermoFormula(YYText());
530         word elementName(foamName(thermoFormula(0, 2)));
531         label nAtoms = atoi(thermoFormula(2, 3).c_str());
533         if
534         (
535             elementName.size()
536          && elementName.find('0') == string::npos
537          && nAtoms
538         )
539         {
540             correctElementName(elementName);
541             currentSpecieComposition[nSpecieElements].elementName =
542                 elementName;
543             currentSpecieComposition[nSpecieElements++].nAtoms = nAtoms;
544         }
546         currentSpecieComposition.setSize(nSpecieElements);
548         HashTable<List<specieElement> >::iterator specieCompositionIter
549         (
550             specieComposition_.find(currentSpecieName)
551         );
553         if (specieCompositionIter != specieComposition_.end())
554         {
555             specieComposition_.erase(specieCompositionIter);
556         }
558         specieComposition_.insert
559         (
560             currentSpecieName,
561             currentSpecieComposition
562         );
564         BEGIN(readThermoLineLabel1);
565     }
567 <readThermoLineLabel1>{thermoLineLabel1} {
568         BEGIN(readThermoCoeff1);
569     }
571 <readThermoCoeff1>{thermoCoeff}{thermoCoeff}{thermoCoeff}{thermoCoeff}{thermoCoeff} {
572         string thermoCoeffString(YYText());
574         highCpCoeffs[0] = stringToScalar(thermoCoeffString(0, 15));
575         highCpCoeffs[1] = stringToScalar(thermoCoeffString(15, 15));
576         highCpCoeffs[2] = stringToScalar(thermoCoeffString(30, 15));
577         highCpCoeffs[3] = stringToScalar(thermoCoeffString(45, 15));
578         highCpCoeffs[4] = stringToScalar(thermoCoeffString(60, 15));
580         BEGIN(readThermoLineLabel2);
581     }
583 <readThermoLineLabel2>{thermoLineLabel2} {
584         BEGIN(readThermoCoeff2);
585     }
587 <readThermoCoeff2>{thermoCoeff}{thermoCoeff}{thermoCoeff}{thermoCoeff}{thermoCoeff} {
588         string thermoCoeffString(YYText());
590         highCpCoeffs[5] = stringToScalar(thermoCoeffString(0, 15));
591         highCpCoeffs[6] = stringToScalar(thermoCoeffString(15, 15));
593         lowCpCoeffs[0] = stringToScalar(thermoCoeffString(30, 15));
594         lowCpCoeffs[1] = stringToScalar(thermoCoeffString(45, 15));
595         lowCpCoeffs[2] = stringToScalar(thermoCoeffString(60, 15));
597         BEGIN(readThermoLineLabel3);
598     }
600 <readThermoLineLabel3>{thermoLineLabel3} {
601         BEGIN(readThermoCoeff3);
602     }
604 <readThermoCoeff3>{thermoCoeff}{thermoCoeff}{thermoCoeff}{thermoCoeff}{thermoCoeff} {
605         string thermoCoeffString(YYText());
607         lowCpCoeffs[3] = stringToScalar(thermoCoeffString(0, 15));
608         lowCpCoeffs[4] = stringToScalar(thermoCoeffString(15, 15));
609         lowCpCoeffs[5] = stringToScalar(thermoCoeffString(30, 15));
610         lowCpCoeffs[6] = stringToScalar(thermoCoeffString(45, 15));
612         BEGIN(readThermoLineLabel4);
613     }
615 <readThermoLineLabel4>{thermoLineLabel4} {
617         HashPtrTable<reactionThermo>::iterator specieThermoIter
618         (
619             speciesThermo_.find(currentSpecieName)
620         );
622         if (specieThermoIter != speciesThermo_.end())
623         {
624             speciesThermo_.erase(specieThermoIter);
625         }
627         speciesThermo_.insert
628         (
629             currentSpecieName,
630             new reactionThermo
631             (
632                 janafThermo<perfectGas>
633                 (
634                     specie
635                     (
636                         currentSpecieName,
637                         1.0,
638                         molecularWeight(currentSpecieComposition)
639                     ),
640                     currentLowT,
641                     currentHighT,
642                     currentCommonT,
643                     highCpCoeffs,
644                     lowCpCoeffs
645                 ),
646                 1.67212e-6,
647                 170.672
648             )
649         );
651         BEGIN(readThermoSpecieName);
652     }
654 <readThermoSpecieName>{end} {
655         BEGIN(INITIAL);
656     }
658  /* ------------------------------------------------------------------------- *\
659     ------ Read reactions
660  \* ------------------------------------------------------------------------- */
662 <INITIAL,readThermoSpecieName>{reactions} {
663         currentSpecieCoeff.stoichCoeff = 1.0;
664         currentSpecieCoeff.exponent = currentSpecieCoeff.stoichCoeff;
665         BEGIN(readReactionsUnits);
666     }
668 <readReactionsUnits>{calPerMol} {
669         RRreactions = RRcal;
670     }
672 <readReactionsUnits>{kcalPerMol} {
673         RRreactions = RRcal/1000.0;
674     }
676 <readReactionsUnits>{joulePerMol} {
677         RRreactions = RRjoule;
678     }
680 <readReactionsUnits>{otherReactionsUnit} {
681     }
683 <readReactionsUnits>\n {
684         lineNo_++;
685         BEGIN(readReactionKeyword);
686     }
688 <readReactionKeyword>{nMoles} {
689         currentSpecieCoeff.stoichCoeff = atof(YYText());
690         currentSpecieCoeff.exponent = currentSpecieCoeff.stoichCoeff;
691     }
693 <readReactionKeyword>{reactionKeyword} {
695         word keyword(foamName(YYText()));
697         HashTable<int>::iterator reactionKeywordIter
698         (
699             reactionKeywordTable_.find(keyword)
700         );
702         if (reactionKeywordIter != reactionKeywordTable_.end())
703         {
704             switch(reactionKeywordIter())
705             {
706                 case duplicateReactionType:
707                 {
708                     BEGIN(readReactionKeyword);
709                     break;
710                 }
712                 case thirdBodyReactionType:
713                 {
714                     if (rrType != Arrhenius && rrType != thirdBodyArrhenius)
715                     {
716                         FatalErrorIn("chemkinReader::lex()")
717                             << "Attempt to set reaction rate type to"
718                                " thirdBodyArrhenius when it is already set to "
719                             << reactionRateTypeNames[rrType]
720                             << " on line " << lineNo_
721                             << exit(FatalError);
722                     }
724                     if (pDependentSpecieName.size())
725                     {
726                         FatalErrorIn("chemkinReader::lex()")
727                             << "A non-pressure dependent third-body appears in"
728                                " the pressure dependent reaction on line "
729                             << lineNo_
730                             << exit(FatalError);
731                     }
733                     rrType = thirdBodyArrhenius;
735                     if (lrhsPtr == &lhs)
736                     {
737                         lhsThirdBodyCounter++;
738                     }
739                     else
740                     {
741                         rhsThirdBodyCounter++;
742                     }
744                     BEGIN(readReactionDelimiter);
745                     break;
746                 }
748                 case plasmaMomentumTransfer:
749                 {
750                     FatalErrorIn("chemkinReader::lex()")
751                         << "Plasma momentum-transfer in reaction on line "
752                         << lineNo_ << "not yet supported"
753                         << exit(FatalError);
755                     BEGIN(readReactionKeyword);
756                     break;
757                 }
759                 case collisionCrossSection:
760                 {
761                     FatalErrorIn("chemkinReader::lex()")
762                         << "Collision cross-section in reaction on line "
763                         << lineNo_ << "not yet supported"
764                         << exit(FatalError);
766                     BEGIN(readReactionKeyword);
767                     break;
768                 }
770                 case end:
771                 {
772                     BEGIN(INITIAL);
773                     addReaction
774                     (
775                         lhs,
776                         rhs,
777                         thirdBodyEfficiencies,
778                         rType,
779                         rrType,
780                         fofType,
781                         ArrheniusCoeffs,
782                         reactionCoeffsTable,
783                         RRreaction
784                     );
785                     finishReaction = false;
786                     rType = unknownReactionType;
787                     rrType = Arrhenius;
788                     fofType = unknownFallOffFunctionType;
789                     thirdBodyEfficiencies = 1.0;
790                     pDependentSpecieName = word::null;
791                     lrhsPtr = &lhs;
792                     break;
793                 }
795                 default:
796                 {
797                     FatalErrorIn("chemkinReader::lex()")
798                         << "keyword " << keyword
799                         << " should be followed by parameters"
800                         << " on line " << lineNo_
801                         << exit(FatalError);
802                 }
803             }
804         }
805         else
806         {
807             currentSpecieName = keyword;
809             HashTable<label>::iterator specieIndexIter
810             (
811                 specieIndices_.find(currentSpecieName)
812             );
814             if (specieIndexIter != specieIndices_.end())
815             {
816                 if (finishReaction)
817                 {
818                     addReaction
819                     (
820                         lhs,
821                         rhs,
822                         thirdBodyEfficiencies,
823                         rType,
824                         rrType,
825                         fofType,
826                         ArrheniusCoeffs,
827                         reactionCoeffsTable,
828                         RRreaction
829                     );
830                     finishReaction = false;
831                     rType = unknownReactionType;
832                     rrType = Arrhenius;
833                     fofType = unknownFallOffFunctionType;
834                     thirdBodyEfficiencies = 1.0;
835                     pDependentSpecieName = word::null;
836                     lrhsPtr = &lhs;
837                 }
839                 currentSpecieCoeff.index = specieIndexIter();
840                 lrhsPtr->append(currentSpecieCoeff);
842                 BEGIN(readReactionDelimiter);
843             }
844             else
845             {
846                 BEGIN(readSpecieNamePlus);
847             }
848         }
849     }
851 <readReactionKeyword>{reactionKeywordSlash} {
853         word keyword(foamName(YYText()));
855         HashTable<int>::iterator reactionKeywordIter
856         (
857             reactionKeywordTable_.find(keyword)
858         );
860         if (reactionKeywordIter != reactionKeywordTable_.end())
861         {
862             switch(reactionKeywordIter())
863             {
864                 case unimolecularFallOffReactionType:
865                 {
866                     if (!pDependentSpecieName.size())
867                     {
868                         FatalErrorIn("chemkinReader::lex()")
869                             << "LOW keyword given for a unimolecular fall-off"
870                                " reaction which does not contain a pressure"
871                                " dependent specie" << " on line " << lineNo_
872                             << exit(FatalError);
873                     }
875                     if (rrType == Arrhenius)
876                     {
877                         rrType = unimolecularFallOff;
878                     }
879                     else
880                     {
881                         FatalErrorIn("chemkinReader::lex()")
882                             << "Attempt to set reaction rate type to"
883                                " unimolecularFallOff when it is already set to "
884                             << reactionRateTypeNames[rrType]
885                             << " on line " << lineNo_
886                             << exit(FatalError);
887                     }
889                     if (fofType == unknownFallOffFunctionType)
890                     {
891                         fofType = Lindemann;
892                     }
894                     reactionCoeffsName = reactionRateTypeNames[rrType];
895                     BEGIN(readReactionCoeffs);
896                     break;
897                 }
899                 case chemicallyActivatedBimolecularReactionType:
900                 {
901                     if (!pDependentSpecieName.size())
902                     {
903                         FatalErrorIn("chemkinReader::lex()")
904                             << "HIGH keyword given for a chemically"
905                                " activated bimolecular reaction which does not"
906                                " contain a pressure dependent specie"
907                             << " on line " << lineNo_
908                             << exit(FatalError);
909                     }
911                     if (rrType == Arrhenius)
912                     {
913                         rrType = chemicallyActivatedBimolecular;
914                     }
915                     else
916                     {
917                         FatalErrorIn("chemkinReader::lex()")
918                             << "Attempt to set reaction rate type to"
919                                " chemicallyActivatedBimolecular when it is"
920                                " already set to "
921                             << reactionRateTypeNames[rrType]
922                             << " on line " << lineNo_
923                             << exit(FatalError);
924                     }
926                     if (fofType == unknownFallOffFunctionType)
927                     {
928                         fofType = Lindemann;
929                     }
931                     reactionCoeffsName = reactionRateTypeNames[rrType];
932                     BEGIN(readReactionCoeffs);
933                     break;
934                 }
936                 case TroeReactionType:
937                 {
938                     if (!pDependentSpecieName.size())
939                     {
940                         FatalErrorIn("chemkinReader::lex()")
941                             << "TROE keyword given for a"
942                                " reaction which does not contain a pressure"
943                                " dependent specie" << " on line " << lineNo_
944                             << exit(FatalError);
945                     }
947                     if
948                     (
949                         fofType == unknownFallOffFunctionType
950                      || fofType == Lindemann
951                     )
952                     {
953                         fofType = Troe;
954                     }
955                     else
956                     {
957                         FatalErrorIn("chemkinReader::lex()")
958                             << "Attempt to set fall-off function type to Troe"
959                                " when it is already set to "
960                             << fallOffFunctionNames[fofType]
961                             << " on line " << lineNo_
962                             << exit(FatalError);
963                     }
965                     reactionCoeffsName = fallOffFunctionNames[fofType];
966                     BEGIN(readReactionCoeffs);
967                     break;
968                 }
970                 case SRIReactionType:
971                 {
972                     if (!pDependentSpecieName.size())
973                     {
974                         FatalErrorIn("chemkinReader::lex()")
975                             << "SRI keyword given for a"
976                                " reaction which does not contain a pressure"
977                                " dependent specie" << " on line " << lineNo_
978                             << exit(FatalError);
979                     }
981                     if
982                     (
983                         fofType == unknownFallOffFunctionType
984                      || fofType == Lindemann
985                     )
986                     {
987                         fofType = SRI;
988                     }
989                     else
990                     {
991                         FatalErrorIn("chemkinReader::lex()")
992                             << "Attempt to set fall-off function type to SRI"
993                                " when it is already set to "
994                             << fallOffFunctionNames[fofType]
995                             << " on line " << lineNo_
996                             << exit(FatalError);
997                     }
999                     reactionCoeffsName = fallOffFunctionNames[fofType];
1000                     BEGIN(readReactionCoeffs);
1001                     break;
1002                 }
1004                 case LandauTellerReactionType:
1005                 {
1006                     if (pDependentSpecieName.size())
1007                     {
1008                         FatalErrorIn("chemkinReader::lex()")
1009                             << "Landau-Teller reaction rate cannot be used"
1010                                " for the pressure-dependent reaction on line "
1011                             << lineNo_
1012                             << exit(FatalError);
1013                     }
1015                     if (rrType == Arrhenius)
1016                     {
1017                         rrType = LandauTeller;
1018                     }
1019                     else
1020                     {
1021                         FatalErrorIn("chemkinReader::lex()")
1022                             << "Attempt to set reaction rate type to"
1023                                " LandauTeller when it is already set to "
1024                             << reactionRateTypeNames[rrType]
1025                             << " on line " << lineNo_
1026                             << exit(FatalError);
1027                     }
1029                     rrType = LandauTeller;
1030                     reactionCoeffsName = reactionRateTypeNames[rrType];
1031                     BEGIN(readReactionCoeffs);
1032                     break;
1033                 }
1035                 case reverseLandauTellerReactionType:
1036                 {
1037                     if (pDependentSpecieName.size())
1038                     {
1039                         FatalErrorIn("chemkinReader::lex()")
1040                             << "Non-equilibrium Landau-Teller reaction rate"
1041                                " cannot be used"
1042                                " for the pressure-dependent reaction on line "
1043                             << lineNo_
1044                             << exit(FatalError);
1045                     }
1047                     if (rType != nonEquilibriumReversible)
1048                     {
1049                         FatalErrorIn("chemkinReader::lex()")
1050                             << "Reverse reaction Arrhenius coefficients not"
1051                                " given for reverse LandauTeller reaction."
1052                                " Please reorder 'REV' keyword to preceed 'RLT'"
1053                             << " on line " << lineNo_
1054                             << exit(FatalError);
1055                     }
1057                     rrType = LandauTeller;
1058                     reactionCoeffsName =
1059                         word(reactionTypeNames[rType])
1060                       + reactionRateTypeNames[rrType];
1061                     BEGIN(readReactionCoeffs);
1062                     break;
1063                 }
1065                 case JanevReactionType:
1066                 {
1067                     if (rrType == Arrhenius)
1068                     {
1069                         rrType = Janev;
1070                     }
1071                     else
1072                     {
1073                         FatalErrorIn("chemkinReader::lex()")
1074                             << "Attempt to set reaction rate type to"
1075                                " Janev when it is already set to "
1076                             << reactionRateTypeNames[rrType]
1077                             << " on line " << lineNo_
1078                             << exit(FatalError);
1079                     }
1081                     reactionCoeffsName = reactionRateTypeNames[rrType];
1082                     BEGIN(readReactionCoeffs);
1083                     break;
1084                 }
1086                 case powerSeriesReactionRateType:
1087                 {
1088                     if (rrType == Arrhenius)
1089                     {
1090                         rrType = powerSeries;
1091                     }
1092                     else
1093                     {
1094                         FatalErrorIn("chemkinReader::lex()")
1095                             << "Attempt to set reaction rate type to"
1096                                " powerSeries when it is already set to "
1097                             << reactionRateTypeNames[rrType]
1098                             << " on line " << lineNo_
1099                             << exit(FatalError);
1100                     }
1102                     reactionCoeffsName = reactionRateTypeNames[rrType];
1103                     BEGIN(readReactionCoeffs);
1104                     break;
1105                 }
1107                 case radiationActivatedReactionType:
1108                 {
1109                     FatalErrorIn("chemkinReader::lex()")
1110                         << "Radiation activated reaction on line "
1111                         << lineNo_ << "not yet supported"
1112                         << exit(FatalError);
1113                     //reactionCoeffsName = reactionRateTypeNames[rrType];
1114                     BEGIN(readReactionCoeffs);
1115                     break;
1116                 }
1118                 case energyLossReactionType:
1119                 {
1120                     FatalErrorIn("chemkinReader::lex()")
1121                         << "Energy loss in reaction on line "
1122                         << lineNo_ << "not yet supported"
1123                         << exit(FatalError);
1124                     //reactionCoeffsName = reactionRateTypeNames[rrType];
1125                     BEGIN(readReactionCoeffs);
1126                     break;
1127                 }
1129                 case nonEquilibriumReversibleReactionType:
1130                 {
1131                     rType = nonEquilibriumReversible;
1132                     reactionCoeffsName = reactionTypeNames[rType];
1133                     BEGIN(readReactionCoeffs);
1134                     break;
1135                 }
1137                 case speciesOrderForward:
1138                 {
1139                     lrhsPtr = &lhs;
1140                     BEGIN(readReactionOrderSpecie);
1141                     break;
1142                 }
1144                 case speciesOrderReverse:
1145                 {
1146                     lrhsPtr = &rhs;
1147                     BEGIN(readReactionOrderSpecie);
1148                     break;
1149                 }
1151                 case UnitsOfReaction:
1152                 {
1153                     BEGIN(readReactionUnit);
1154                     break;
1155                 }
1157                 default:
1158                 {
1159                     FatalErrorIn("chemkinReader::lex()")
1160                         << "unknown reaction keyword " << keyword
1161                         << " on line " << lineNo_
1162                         << exit(FatalError);
1163                 }
1164             }
1165         }
1166         else
1167         {
1168             HashTable<label>::iterator specieIndexIter
1169             (
1170                 specieIndices_.find(keyword)
1171             );
1173             if (specieIndexIter != specieIndices_.end())
1174             {
1175                 currentThirdBodyIndex = specieIndexIter();
1176             }
1177             else
1178             {
1179                 FatalErrorIn("chemkinReader::lex()")
1180                     << "unknown third-body specie " << keyword
1181                     << " on line " << lineNo_ << nl
1182                     << "Valid species are : " << nl
1183                     << specieIndices_.toc() << endl
1184                     << exit(FatalError);
1185             }
1187             BEGIN(readThirdBodyEfficiency);
1188         }
1189     }
1191 <readSpecieNamePlus>"+" {
1192         currentSpecieName += "+";
1194         HashTable<label>::iterator specieIndexIter
1195         (
1196             specieIndices_.find(currentSpecieName)
1197         );
1199         if (specieIndexIter != specieIndices_.end())
1200         {
1201             if (finishReaction)
1202             {
1203                 addReaction
1204                 (
1205                     lhs,
1206                     rhs,
1207                     thirdBodyEfficiencies,
1208                     rType,
1209                     rrType,
1210                     fofType,
1211                     ArrheniusCoeffs,
1212                     reactionCoeffsTable,
1213                     RRreaction
1214                 );
1215                 finishReaction = false;
1216                 rType = unknownReactionType;
1217                 rrType = Arrhenius;
1218                 fofType = unknownFallOffFunctionType;
1219                 thirdBodyEfficiencies = 1.0;
1220                 pDependentSpecieName = word::null;
1221                 lrhsPtr = &lhs;
1222             }
1224             currentSpecieCoeff.index = specieIndexIter();
1225             lrhsPtr->append(currentSpecieCoeff);
1227             BEGIN(readReactionDelimiter);
1228         }
1229         else
1230         {
1231             FatalErrorIn("chemkinReader::lex()")
1232                 << "unknown specie " << currentSpecieName
1233                 << " on line " << lineNo_ << nl
1234                 << "Valid species are : " << nl
1235                 << specieIndices_.toc() << endl
1236                 << exit(FatalError);
1237         }
1238     }
1240 <readReactionDelimiter>{specieDelimiter} {
1241         currentSpecieCoeff.stoichCoeff = 1.0;
1242         currentSpecieCoeff.exponent = currentSpecieCoeff.stoichCoeff;
1243         BEGIN(readReactionKeyword);
1244     }
1246 <readReactionDelimiter>{irreversibleReactionDelimiter} {
1247         currentSpecieCoeff.stoichCoeff = 1.0;
1248         currentSpecieCoeff.exponent = currentSpecieCoeff.stoichCoeff;
1249         rType = irreversible;
1250         lrhsPtr = &rhs;
1251         BEGIN(readReactionKeyword);
1252     }
1254 <readReactionDelimiter>{reversibleReactionDelimiter} {
1255         currentSpecieCoeff.stoichCoeff = 1.0;
1256         currentSpecieCoeff.exponent = currentSpecieCoeff.stoichCoeff;
1257         rType = reversible;
1258         lrhsPtr = &rhs;
1259         BEGIN(readReactionKeyword);
1260     }
1262 <readReactionDelimiter>& {
1263     }
1265 <readReactionDelimiter>{reactionCoeffs} {
1266         string reactionCoeffsString(YYText());
1267         reactionCoeffsString.replaceAll("d", "e");
1268         reactionCoeffsString.replaceAll("D", "e");
1269         IStringStream reactionCoeffsStream(reactionCoeffsString);
1270         reactionCoeffsStream.lineNumber() = lineNo_;
1272         reactionCoeffsStream
1273             >> ArrheniusCoeffs[0]
1274             >> ArrheniusCoeffs[1]
1275             >> ArrheniusCoeffs[2];
1277         finishReaction = true;
1278         currentSpecieCoeff.stoichCoeff = 1.0;
1279         currentSpecieCoeff.exponent = currentSpecieCoeff.stoichCoeff;
1280         RRreaction = RRreactions;
1282         if (lhsThirdBodyCounter || rhsThirdBodyCounter)
1283         {
1284             if (!lhsThirdBodyCounter || !rhsThirdBodyCounter)
1285             {
1286                 FatalErrorIn("chemkinReader::lex()")
1287                     << "Third body not present on both sides of reaction"
1288                        " on line " << lineNo_
1289                 << exit(FatalError);
1290             }
1292             if (lhsThirdBodyCounter != 1)
1293             {
1294                 FatalErrorIn("chemkinReader::lex()")
1295                     << "More than 1 third body present on l.h.s. side"
1296                        " of reaction on line " << lineNo_
1297                     << exit(FatalError);
1298             }
1300             if (rhsThirdBodyCounter != 1)
1301             {
1302                 FatalErrorIn("chemkinReader::lex()")
1303                     << "More than 1 third body present on r.h.s. side"
1304                        " of reaction on line " << lineNo_
1305                     << exit(FatalError);
1306             }
1308             lhsThirdBodyCounter = 0;
1309             rhsThirdBodyCounter = 0;
1310         }
1312         BEGIN(readReactionKeyword);
1313     }
1316 <readThirdBodyEfficiency>{thirdBodyEfficiency} {
1317         thirdBodyEfficiencies[currentThirdBodyIndex] = stringToScalar(YYText());
1318         BEGIN(readReactionKeyword);
1319     }
1321 <readReactionDelimiter>{startPDependentSpecie} {
1322         BEGIN(readPDependentSpecie);
1323     }
1325 <readPDependentSpecie>{pDependentSpecie} {
1327         word rhsPDependentSpecieName = pDependentSpecieName;
1328         pDependentSpecieName =
1329             foamName(foamSpecieString(YYText()));
1330         pDependentSpecieName =
1331             pDependentSpecieName(0, pDependentSpecieName.size() - 1);
1333         if (rrType == thirdBodyArrhenius)
1334         {
1335             FatalErrorIn("chemkinReader::lex()")
1336                 << "The pressure-dependent third-body '"
1337                 << pDependentSpecieName
1338                 << "' is given in non-pressure-dependent third-body reaction"
1339                 << " on line " << lineNo_
1340                 << exit(FatalError);
1341         }
1343         if (lrhsPtr == &lhs)
1344         {
1345             lhsThirdBodyCounter++;
1346         }
1347         else
1348         {
1349             if (pDependentSpecieName != rhsPDependentSpecieName)
1350             {
1351                 FatalErrorIn("chemkinReader::lex()")
1352                     << "The third-body reactant '"
1353                     << pDependentSpecieName
1354                     << "' is not the same as the third-body product '"
1355                     << rhsPDependentSpecieName
1356                     << "' in pressure-dependent reaction on line " << lineNo_
1357                     << exit(FatalError);
1358             }
1360             rhsThirdBodyCounter++;
1361         }
1363         if (pDependentSpecieName != "M")
1364         {
1365             HashTable<label>::iterator specieIndexIter
1366             (
1367                 specieIndices_.find(pDependentSpecieName)
1368             );
1370             if (specieIndexIter != specieIndices_.end())
1371             {
1372                 thirdBodyEfficiencies = 0.0;
1373                 thirdBodyEfficiencies[specieIndexIter()] = 1.0;
1374             }
1375             else
1376             {
1377                 FatalErrorIn("chemkinReader::lex()")
1378                     << "unknown third-body specie " << pDependentSpecieName
1379                     << " on line " << lineNo_ << nl
1380                     << "Valid species are : " << nl
1381                     << specieIndices_.toc() << endl
1382                     << exit(FatalError);
1383             }
1384         }
1386         BEGIN(readReactionDelimiter);
1387     }
1389 <readReactionCoeffs>{reactionCoeff} {
1390         reactionCoeffs.append(stringToScalar(YYText()));
1391     }
1393 <readReactionCoeffs>{endReactionCoeffs} {
1394         reactionCoeffsTable.insert(reactionCoeffsName, reactionCoeffs.shrink());
1395         reactionCoeffs.clear();
1396         BEGIN(readReactionKeyword);
1397     }
1399 <readTdepSpecie>{specieName} {
1400         word specieName(foamName(foamSpecieString(YYText())));
1401         FatalErrorIn("chemkinReader::lex()")
1402             << "Temperature-dependent reaction on line "
1403             << lineNo_ << "not yet supported"
1404             << exit(FatalError);
1405         BEGIN(readReactionKeyword);
1406     }
1408 <readReactionOrderSpecie>{specieName} {
1409         currentSpecieName =
1410             word(foamName(foamSpecieString(YYText())));
1412         HashTable<label>::iterator specieIndexIter
1413         (
1414             specieIndices_.find(currentSpecieName)
1415         );
1417         if (specieIndexIter != specieIndices_.end())
1418         {
1419             currentSpecieIndex = specieIndexIter();
1420         }
1421         else
1422         {
1423             FatalErrorIn("chemkinReader::lex()")
1424                 << "unknown specie " << currentSpecieName
1425                 << " given in reaction-order specification"
1426                 << " on line " << lineNo_ << nl
1427                 << "Valid species are : " << nl
1428                 << specieIndices_.toc() << endl
1429                 << exit(FatalError);
1430         }
1432         BEGIN(readReactionOrder);
1433     }
1435 <readReactionOrder>{reactionCoeff}{endReactionCoeffs} {
1437         DynamicList<reaction::specieCoeffs>& lrhs = *lrhsPtr;
1439         bool found = false;
1441         forAll (lrhs, i)
1442         {
1443             if (lrhs[i].index == currentSpecieIndex)
1444             {
1445                 lrhs[i].exponent = stringToScalar(YYText());
1446                 found = true;
1447                 break;
1448             }
1449         }
1451         if (!found)
1452         {
1453             word side("l.h.s.");
1455             if (lrhsPtr == &rhs)
1456             {
1457                 side = "r.h.s.";
1458             }
1460             FatalErrorIn("chemkinReader::lex()")
1461                 << "Specie " << currentSpecieName
1462                 << " on line " << lineNo_
1463                 << " not present in " << side << " of reaction " << nl << lrhs
1464                 << exit(FatalError);
1465         }
1467         BEGIN(readReactionKeyword);
1468     }
1470 <readReactionUnit>{cal} {
1471         RRreaction = RRcal;
1472     }
1474 <readReactionUnit>{kcal} {
1475         RRreaction = RRcal/1000.0;
1476     }
1478 <readReactionUnit>{joule} {
1479         RRreaction = RRjoule;
1480     }
1482 <readReactionUnit>{kjoule} {
1483         RRreaction = RRjoule/1000.0;
1484     }
1486 <readReactionUnit>{otherReactionsUnit} {
1487     }
1489 <readReactionUnit>{endReactionCoeffs} {
1490         BEGIN(readReactionKeyword);
1491     }
1494  /* ------------------ Ignore remaining space and \n s. --------------------- */
1496 <*>\n      { lineNo_++; }
1498  /* ------ Ignore remaining space and \n s.  Any other characters are errors. */
1500 <*>. {
1501         startError = YYText();
1502         yy_push_state(CHEMKINError);
1503     }
1505 <CHEMKINError>.* {
1506         yy_pop_state();
1507         FatalErrorIn("chemkinReader::lex()")
1508             << "while " << stateNames[YY_START] << " on line " << lineNo_ << nl
1509             << "    expected " << stateExpects[YY_START]
1510             << " but found '" << startError << YYText() << "'"
1511             << exit(FatalError);
1512     }
1515  /*  ------------------------ On EOF terminate. ----------------------------  */
1517 <<EOF>> {
1518         if (finishReaction)
1519         {
1520             addReaction
1521             (
1522                 lhs,
1523                 rhs,
1524                 thirdBodyEfficiencies,
1525                 rType,
1526                 rrType,
1527                 fofType,
1528                 ArrheniusCoeffs,
1529                 reactionCoeffsTable,
1530                 RRreaction
1531             );
1532         }
1533         yyterminate();
1534     }
1537  /* ------------------------------------------------------------------------- *\
1538     ------ End of STLToFoam.L
1539  \* ------------------------------------------------------------------------- */