File: N:\mfix\model\parse_mod.f

1     MODULE parse
2     
3        USE compar
4        USE exit, only: mfix_exit
5        USE funits
6        USE param
7        USE param1
8     
9           IMPLICIT NONE
10     
11     ! Strings indicating arithmetic operation and reaction blocks.
12           CHARACTER(LEN=2), PARAMETER :: START_STR = '@('  ! start
13           CHARACTER(LEN=1), PARAMETER :: END_STR = ')'     ! end
14     
15     ! Strings indicating reaction blocks.
16           CHARACTER(LEN=4), PARAMETER :: RXN_BLK     = 'RXNS'      ! start block
17           CHARACTER(LEN=8), PARAMETER :: DES_RXN_BLK = 'DES_RXNS'  ! start block
18           CHARACTER(LEN=3), PARAMETER :: END_BLK     = 'END'       ! end block
19     
20           LOGICAL READING_RXN
21           LOGICAL READING_RATE
22     
23           LOGICAL DES_RXN
24           LOGICAL TFM_RXN
25     
26     ! Logical indicating that the start of a reaction construct has
27     ! been identified.
28           LOGICAL IN_CONSTRUCT
29     
30     ! Logical indicating that the chemical equation spans additional lines.
31           LOGICAL MORE_ChemEq
32     
33     ! Reaction names
34           CHARACTER(len=32),  DIMENSION(:),   ALLOCATABLE :: RXN_NAME
35     ! chemical Equations
36           CHARACTER(len=512), DIMENSION(:),   ALLOCATABLE :: RXN_CHEM_EQ
37     ! User defined heat of reaction
38           DOUBLE PRECISION,   DIMENSION(:),   ALLOCATABLE :: usrDH
39     ! User defined heat of reaction partitions.
40           DOUBLE PRECISION,   DIMENSION(:,:), ALLOCATABLE :: usrfDH
41     
42     
43     ! Logical indicating that the start of a reaction construct has
44     ! been identified.
45           LOGICAL IN_DES_CONSTRUCT
46     
47     ! Reaction names
48           CHARACTER(len=32),  DIMENSION(:),   ALLOCATABLE :: DES_RXN_NAME
49     ! chemical Equations
50           CHARACTER(len=512), DIMENSION(:),   ALLOCATABLE :: DES_RXN_CHEM_EQ
51     ! User defined heat of reaction
52           DOUBLE PRECISION,   DIMENSION(:),   ALLOCATABLE :: DES_usrDH
53     ! User defined heat of reaction partitions.
54           DOUBLE PRECISION,   DIMENSION(:,:), ALLOCATABLE :: DES_usrfDH
55     
56           CONTAINS
57     
58     !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
59     !  Function name: setReaction                                          !
60     !                                                                      !
61     !  Purpose:                                                            !
62     !                                                                      !
63     !  Variables referenced: None                                          !
64     !                                                                      !
65     !  Variables modified: None                                            !
66     !                                                                      !
67     !  Local variables: None                                               !
68     !                                                                      !
69     !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
70           SUBROUTINE setReaction(RxN, lNg, lSAg, lM, lNs, lSAs, lDH, lfDH)
71     
72           use rxn_com
73           use toleranc
74     
75           IMPLICIT NONE
76     
77     ! Pass Arguments:
78     !---------------------------------------------------------------------//
79     ! Data structure for storing reaction data.
80           TYPE(REACTION_BLOCK), POINTER, INTENT(INOUT) :: RxN
81     ! Number of gas speices
82           INTEGER, INTENT(IN) :: lNg
83     ! Gas phase species aliases
84           CHARACTER(len=32), DIMENSION(DIM_N_g), INTENT(IN) :: lSAg
85     ! Number of solids phases
86           INTEGER, INTENT(IN) :: lM
87     ! Number of species in each solids phase.
88           INTEGER, DIMENSION(DIM_M), INTENT(IN) :: lNs
89     ! Solids phase speices aliases.
90           CHARACTER(len=32), DIMENSION(DIM_M, DIM_N_s), INTENT(IN) :: lSAs
91     ! User defined heat of reaction.
92           DOUBLE PRECISION, INTENT(IN) :: lDH
93     ! User defined heat of reaction partition.
94           DOUBLE PRECISION, DIMENSION(0:DIM_M), INTENT(IN) :: lfDH
95     
96     ! Local Variables:
97     !---------------------------------------------------------------------//
98     ! Alias, phase, species, stoich coeff :: Reactants    Products
99           CHARACTER(LEN=32), DIMENSION(50)     :: rAlias    ,  pAlias
100           DOUBLE PRECISION, DIMENSION(50) :: rCoeff    ,  pCoeff
101     
102     ! Number of products and reactants
103           INTEGER rNo, pNo
104     ! Positions in ChemEq delineating the reactants and products.
105           INTEGER rEnd, pStart
106     ! Loop counters
107           INTEGER L, LL, M, lN
108     
109     ! Sum of user specified heat of reaction partitions. If fracDH is set
110     ! by the user, they must sum to one over all phases.
111           DOUBLE PRECISION sumFDH
112     ! Local storage for chemical equations, left-adjusted and trimmed
113           CHARACTER(LEN=512) lChemEq
114     ! Local storage for reaction name, left-adjusted and trimmed
115           CHARACTER(LEN=32)  lName
116     ! Logical indicating the reaction is skipped.
117           LOGICAL Skip
118     
119           LOGICAL pMap(0:lM)
120     
121           INTEGER nSpecies, nPhases
122     
123           LOGICAL blankAlias(0:(DIM_N_g + lM*DIM_N_s))
124     
125     ! Initialize local reaction name and chemical equation variables.
126           lName = trim(adjustl(RxN%Name))
127           lChemEq = trim(adjustl(RxN%ChemEq))
128     
129           RxN%Classification = "Undefined"
130           RxN%Calc_DH = .TRUE.
131           RxN%nSpecies = 0
132           RxN%nPhases = 0
133     
134     ! Verify that the reactants are separated by --> or = signs. If the
135     ! chemical equation is NONE, the reaction is skipped.
136           CALL checkSplit(lName, lChemEq, rEnd, pStart, Skip)
137           IF(Skip) THEN
138              RxN%nSpecies = 0
139              RETURN
140           ENDIF
141     ! Set the flag to calculate heat of reaction.
142           RxN%Calc_DH = .TRUE.
143           IF(lDH /= UNDEFINED) RxN%Calc_DH = .FALSE.
144     
145     ! Pull off the reactants from the chemical equations.
146           CALL splitEntries(lName, lChemEq, 1, rEnd, rNo, rAlias, rCoeff)
147     ! Pull off the products from the chemical equations.
148           CALL splitEntries(lName, lChemEq, pStart, len_trim(lChemEq),     &
149              pNo, pAlias, pCoeff)
150     
151           nSpecies = rNo + pNo
152           RxN%nSpecies = nSpecies
153           Allocate( RxN%Species( nSpecies ))
154     
155           CALL checkBlankAliases(lNg, lSAg, lM, lNs, lSAs, blankAlias)
156     
157     ! Check that species in the chemical equation match a species alias
158     ! in one of the phases.
159           CALL mapAliases(lName, lChemEq, lNg, lSAg, lM, lNs, lSAs, rNo,   &
160              rAlias, rCoeff, -ONE, 0, blankAlias, RxN)
161     
162     ! Check that species in the chemical equation match a species alias
163     ! in one of the phases.
164           CALL mapAliases(lName, lChemEq, lNg, lSAg, lM, lNs, lSAs, pNo,   &
165              pAlias, pCoeff, ONE, rNo, blankAlias, RxN)
166     
167     ! All the relevant data has been collected at this point. Build the
168     ! reaction block data structure.
169           L = max(1,lM)
170           LL = (L * (L-1)/2)
171           Allocate( RxN%rPhase( LL+L ))
172     
173     
174     ! Initialize local map and global values
175           pMap(:) = .FALSE.
176           nPhases = 0
177           DO lN = 1, nSpecies
178              M = RxN%Species(lN)%pMap
179     
180              RxN%Species(lN)%mXfr = M
181              RxN%Species(lN)%xXfr = ZERO
182     
183              IF(.NOT.pMap(M)) THEN
184                 pMap(M) = .TRUE.
185                 nPhases = nPhases + 1
186              ENDIF
187           ENDDO
188           RxN%nPhases = nPhases
189     
190     ! Initialize sum of heat of reaction partitions.
191           sumFDH = ZERO
192     ! The user specified the heat of reaction.
193           IF(.NOT.RxN%Calc_DH) THEN
194     ! Allocate and initialize the heat of reaction storage array.
195              Allocate( RxN%HoR( 0:lM ))
196              RxN%HoR(:) = ZERO
197              DO M=0,lM
198     ! The phase is referenced by the reaction and heat of reaction is
199     ! allocated (in part or fully) this this phase.
200                 IF(pMap(M) .AND. lFDH(M) .NE. UNDEFINED) THEN
201     ! Store the heat of reaction.
202                    RxN%HoR(M) = lFDH(M) * lDH
203                    sumFDH = sumFDH + lFDH(M)
204     ! The phase is not referenced by the reaction, but the heat of reaction
205     ! is allocated (in part or fully) to this phase. Flag error and exit.
206                 ELSEIF(.NOT.pMap(M) .AND. lFDH(M) .NE. UNDEFINED) THEN
207                    IF(myPE == PE_IO) THEN
208                       write(*,1000) trim(lName)
209                       write(*,1001)
210                       write(*,1010)
211     ! Write message to log file.
212                       write(UNIT_LOG,1000) trim(lName)
213                       write(UNIT_LOG,1001)
214                       write(UNIT_LOG,1010)
215                    ENDIF
216     ! Exit MFIX
217                    CALL MFIX_EXIT(myPE)
218                 ENDIF
219              ENDDO
220     ! Logical check: No partition was assigned to an undefined phase.
221              DO M=lM+1,DIM_M
222                 IF(.NOT.RxN%Calc_DH .AND. lFDH(M) .NE. UNDEFINED) THEN
223                    IF(myPE == PE_IO) THEN
224                       write(*,1000) trim(lName)
225                       write(*,1001)
226                       write(*,1010)
227     ! Write message to log file.
228                       write(UNIT_LOG,1000) trim(lName)
229                       write(UNIT_LOG,1001)
230                       write(UNIT_LOG,1010)
231     ! Exit MFIX
232                    ENDIF
233                    CALL MFIX_EXIT(myPE)
234                 ENDIF
235              ENDDO
236           ENDIF
237     
238     ! Verify that the heat of reaction partitions sum to one.
239           IF(.NOT.RxN%Calc_DH .AND. .NOT. COMPARE(sumFDH, ONE)) THEN
240              IF(myPE == PE_IO) THEN
241                 write(*,1002) trim(lName)
242                 write(*,1010)
243     ! Write message to log file.
244                 write(UNIT_LOG,1002) trim(lName)
245                 write(UNIT_LOG,1010)
246     ! Exit MFIX
247                 CALL MFIX_EXIT(myPE)
248              ENDIF
249           ENDIF
250     
251           RETURN
252     
253      1000 FORMAT(/1X,70('*')/' From: From: setReaction:',/                 &
254              ' Message: Heat of reaction is proportioned to a phase not',  &
255              ' referenced',/' by the chemical equation for reaction ',A,'.')
256     
257      1001 FORMAT(/' If this is a catalytic reaction, reference one of the',&
258              ' species of the',/' catalyst phase within the chemical',     &
259              ' equation with a stoichiometric',/' coefficient of zero.'/)
260     
261      1002 FORMAT(/1X,70('*')/' From: From: setReaction:',/                 &
262              ' Message: The heat of reaction partitions (fracDH) to all',  &
263              ' phases do',/' not sum to one for reaction ',A,'.')
264     
265      1010 FORMAT(' Please refer to the Readme file for chemical equation', &
266              ' input formats',/' and correct the data file.',/1X,70('*')/)
267     
268     
269           END SUBROUTINE setReaction
270     
271     
272     !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
273     !  Function name: checkSplit                                           !
274     !                                                                      !
275     !  Purpose: Determine the location of reactatns and products within    !
276     !  the chemical equation. If the entry is NONE, flag that the reaction !
277     !  is to be skipped for further processing.                            !
278     !                                                                      !
279     !  Variables referenced: None                                          !
280     !                                                                      !
281     !  Variables modified: None                                            !
282     !                                                                      !
283     !  Local variables: None                                               !
284     !                                                                      !
285     !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
286           SUBROUTINE checkSplit(lName, lChemEq, lrEnd, lpStart, lSkip)
287     
288           IMPLICIT NONE
289     
290     ! Pass Arguments:
291     !---------------------------------------------------------------------//
292     ! Chemical reaction name.
293           CHARACTER(len=*), INTENT(IN) :: lName
294     ! Chemical Equation from deck file.
295           CHARACTER(len=*), INTENT(IN) :: lChemEq
296     ! Position specifying the end of the reactants in lChemEq
297           INTEGER, INTENT(OUT) :: lrEnd
298     ! Position specifying the start of the products in lChemEq
299           INTEGER, INTENT(OUT) :: lpStart
300     ! If the chemical equation is NONE, the the skip flag is set to avoid
301     ! further processing.
302           LOGICAL, INTENT(OUT) :: lSkip
303     
304     ! Local Variables:
305     !---------------------------------------------------------------------//
306     ! Position of the head (>) and tail (-) of an arror (-->)
307           INTEGER hArr, tArr
308     ! Postion of the head and tail of equal signs (=, ==, ===, ...)
309           INTEGER hEqs, tEqs
310     ! Position of the head/tail of a reverse arrow (<--)
311           INTEGER hRArr, tRArr
312     ! A flag generated to point out the location of the entry error.
313           CHARACTER(LEN=512) FLAG
314           FLAG = ''
315     
316     ! If the chemical equation is set to 'none', then the reaction is
317     ! skipped for the simulation.
318           lSkip = .FALSE.
319           IF(INDEX(lChemEq,'NONE') > 0) THEN
320              lSkip = .TRUE.
321              lrEnd = UNDEFINED_I
322              lpStart = UNDEFINED_I
323              RETURN
324           ENDIF
325     
326     ! Search for > (part of -->) and search for < (part of <--)
327           tArr = INDEX(lChemEq,'-', BACK=.FALSE.)
328           hArr = INDEX(lChemEq,">", BACK=.TRUE.)
329     ! Search for the first and last instances of equal signs.
330           tEqs = INDEX(lChemEq,"=", BACK=.FALSE.)
331           hEqs = INDEX(lChemEq,"=", BACK=.TRUE.)
332     ! Search for < (as part of <-- or <-->). Illegal chemical equation.
333           hRArr = INDEX(lChemEq,"<", BACK=.FALSE.)
334           tRArr = INDEX(lChemEq,"-", BACK=.TRUE.)
335     
336     ! An illegal arrow was found! Flag error and exit.
337           IF(hRArr > 0) THEN
338              IF(myPE == PE_IO) THEN
339     ! Construct the error flag.
340                 IF(hArr > 0) THEN
341                    FLAG = setFlag(20, hRArr, hArr)
342                 ELSEIF(tRArr > 0) THEN
343                    FLAG = setFlag(20, hRArr, tRArr)
344                 ELSE
345                    FLAG = setFlag(20, hRArr)
346                 ENDIF
347     ! Write the message to the screen.
348                 write(*,1000) trim(lName)
349                 write(*,1002)'Illegal'
350                 write(*,1010) trim(lChemEq), trim(Flag)
351                 write(*,1001)
352     ! Write message to log file.
353                 write(UNIT_LOG,1000) trim(lName)
354                 write(UNIT_LOG,1002)'Illegal'
355                 write(UNIT_LOG,1010) trim(lChemEq), trim(Flag)
356                 write(UNIT_LOG,1001)
357     ! Exit MFIX
358                 CALL MFIX_EXIT(myPE)
359              ENDIF
360           ENDIF
361     ! If there are more than one operator, flag error and exit.
362           IF(hArr /= 0 .AND. hEqs /= 0) THEN
363              IF(myPE == PE_IO) THEN
364     ! Construct the error flag.
365                 FLAG = setFlag(20, hArr, hEqs)
366     ! Write the message to the screen.
367                 write(*,1000) trim(lName)
368                 write(*,1002)'Too many'
369                 write(*,1010) trim(lChemEq), trim(Flag)
370                 write(*,1001)
371     ! Write message to log file.
372                 write(UNIT_LOG,1000) trim(lName)
373                 write(UNIT_LOG,1002)'Too many'
374                 write(UNIT_LOG,1010) trim(lChemEq), trim(Flag)
375                 write(UNIT_LOG,1001)
376     ! Exit MFIX
377                 CALL MFIX_EXIT(myPE)
378              ENDIF
379     ! If there is no operator (--> or =), flag error and exit.
380           ELSEIF(hArr == 0 .AND. hEqs == 0) THEN
381              IF(myPE == PE_IO) THEN
382                 write(*,1000) trim(lName)
383                 write(*,1002) 'No'
384                 write(*,1011) trim(lChemEq)
385                 write(*,1001)
386     ! Write message to log file.
387                 write(UNIT_LOG,1000) trim(lName)
388                 write(UNIT_LOG,1002) 'No'
389                 write(UNIT_LOG,1011) trim(lChemEq)
390                 write(UNIT_LOG,1001)
391     ! Exit MFIX
392                 CALL MFIX_EXIT(myPE)
393              ENDIF
394     ! The head of an arrow was found.
395           ELSEIF(hArr /= 0) THEN
396     ! Verify that a tail was found.
397              IF(tArr == 0) THEN
398     ! Construct the error flag.
399                 FLAG = setFlag(20, hArr)
400                 IF(myPE == PE_IO) THEN
401                    write(*,1000) trim(lName)
402                    write(*,1003) 'Missing the tail; -->'
403                    write(*,1010) trim(lChemEq), trim(Flag)
404                    write(*,1001)
405     ! Write message to log file.
406                    write(UNIT_LOG,1000) trim(lName)
407                    write(UNIT_LOG,1003) 'Missing the tail; -->'
408                    write(UNIT_LOG,1010) trim(lChemEq), trim(Flag)
409                    write(UNIT_LOG,1001)
410     ! Exit MFIX
411                    CALL MFIX_EXIT(myPE)
412                 ENDIF
413              ELSEIF(tArr > hArr) THEN
414                 IF(myPE == PE_IO) THEN
415                    FLAG = setFlag(20, hArr, INDEX(lChemEq,'-',BACK=.TRUE.))
416                    write(*,1000) trim(lName)
417                    write(*,1003) 'Arror head preceeds the tail; -->'
418                    write(*,1010) trim(lChemEq), trim(Flag)
419                    write(*,1001)
420     ! Write message to log file.
421                    write(UNIT_LOG,1000) trim(lName)
422                    write(UNIT_LOG,1003) 'Arror head preceeds the tail; -->'
423                    write(UNIT_LOG,1010) trim(lChemEq), trim(Flag)
424                    write(UNIT_LOG,1001)
425     ! Exit MFIX
426                    CALL MFIX_EXIT(myPE)
427                 ENDIF
428              ELSE
429     ! An arror was used to seperate reactants and products. Send back the
430     ! ending index of reactants and the starting index for products.
431                 lrEnd = tArr - 1
432                 lpStart = hArr + 1
433              ENDIF
434     ! Equals sign(s) were used to specify the reaction. Send back the ending
435     ! index of reactants and the starting index for products.
436           ELSEIF(hEqs /= 0) THEN
437              lrEnd = tEqs - 1
438              lpStart = hEqs + 1
439     ! Fatal Error. One of the above checks should have caught any problems
440     ! and sent out an error message.
441           ELSE
442              IF(myPE == PE_IO) THEN
443                 write(*,1000) trim(lName)
444                 write(*,1004)
445                 write(*,1011) trim(lChemEq)
446                 write(*,1001)
447     ! Write message to log file.
448                 write(UNIT_LOG,1000) trim(lName)
449                 write(UNIT_LOG,1004)
450                 write(UNIT_LOG,1010) trim(lChemEq), trim(Flag)
451                 write(UNIT_LOG,1001)
452     ! Exit MFIX
453                 CALL MFIX_EXIT(myPE)
454              ENDIF
455           ENDIF
456     
457           RETURN
458     
459      1000 FORMAT(/1X,70('*')/' From: From: setReaction --> checkSplit',/   &
460              ' Message: Error in determining the reactants and products',  &
461              ' in the',/' chemical equation for reaction ',A,'.')
462     
463      1001 FORMAT(' Please refer to the Readme file for chemical equation', &
464              ' input formats',/' and correct the data file.',/1X,70('*')/)
465     
466      1002 FORMAT(/1X,A,' operators were found!')
467     
468      1003 FORMAT(' Incorrect operator format! ',A)
469     
470      1004 FORMAT(' FATAL ERROR: All logical checks failed.')
471     
472      1010 FORMAT(/' Chemical Equation: ',A,/1X, A/)
473     
474      1011 FORMAT(/' Chemical Equation: ',A,/)
475     
476     
477           END SUBROUTINE checkSplit
478     
479     
480     !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
481     !  Function name: splitEntries()                                       !
482     !                                                                      !
483     !  Purpose: Takes a string of either reactants or products and splits  !
484     !  the string into individual species/stoichiometric entries.          !
485     !                                                                      !
486     !  A call to splitAliasAndCoeff is made to further split the entries   !
487     !  into species aliases and matching stoichiometric coefficients.      !
488     !                                                                      !
489     !  Variables referenced: None                                          !
490     !                                                                      !
491     !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
492           SUBROUTINE splitEntries(lName, lChemEq, lStart, lEnd, lNo,       &
493              lAlias, lCoeff)
494     
495           IMPLICIT NONE
496     
497     ! Pass Arguments:
498     !---------------------------------------------------------------------//
499     ! Chemical reaction name.
500           CHARACTER(len=*), INTENT(IN) :: lName
501     ! Chemical Equation.
502           CHARACTER(len=*), INTENT(IN) :: lChemEq
503     ! Starting position for substring analysis.
504           INTEGER, INTENT(IN) :: lStart
505     ! Ending position for substring analysis.
506           INTEGER, INTENT(IN) :: lEnd
507     ! The number of individual species found in lSpecies.
508           INTEGER, INTENT(OUT) :: lNo
509     ! Species Aliases from the chemical equation.
510           CHARACTER(LEN=32), DIMENSION(50), INTENT(OUT) :: lAlias
511     ! Stoichiometric coefficient pulled from the chemical equation.
512           DOUBLE PRECISION, DIMENSION(50), INTENT(OUT) :: lCoeff
513     
514     ! Local Variables:
515     !---------------------------------------------------------------------//
516     ! Flag indicating that there are more entries to process.
517           LOGICAL MORE
518     ! Starting position for left-to-right search.
519           INTEGER lPOS
520     ! Position of plus sign charachter found in search.
521           INTEGER rPOS
522     
523     ! Initialize storage variables.
524           lNo = 0
525           lAlias(:) = ''
526           lCoeff(:) = UNDEFINED
527     
528     ! Initialiase local variables.
529           lPOS = lStart
530           MORE = .TRUE.
531     ! Loop through the string, splitting entries separated by a plus sign.
532           DO WHILE(MORE)
533     ! Increment the species counter.
534              lNo = lNo + 1
535     ! Locate the plus sign. (Left to right)
536              rPOS = (lPOS-1) + INDEX(lChemEq(lPOS:lEnd),"+", BACK=.FALSE.)
537     ! A plus sign was found.
538              IF(rPOS .GT. lPOS) THEN
539     ! Extract the entry and split it into the species alias and
540     ! stoichiometric coefficient.
541                 CALL splitAliasAndCoeff(lName, lChemEq, lPOS, rPOS-1,      &
542                    lAlias(lNo), lCoeff(lNo))
543     ! Indicate that there are more entries to process.
544                 MORE = .TRUE.
545     ! No plus sign was found. This is the last entry.
546              ELSE
547     ! Extract the entry and split it into the species alias and
548     ! stoichiometric coefficient.
549                 CALL splitAliasAndCoeff(lName, lChemEq, lPOS, lEnd,        &
550                    lAlias(lNo), lCoeff(lNo))
551     ! Indicate that there are no more entries to process.
552                 MORE = .FALSE.
553              ENDIF
554     ! Move past the found plus sign for next search.
555              lPOS = rPOS + 1
556           ENDDO
557     
558           RETURN
559           END SUBROUTINE splitEntries
560     
561     !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
562     !  Function name: splitAliasAndCoeff()                                 !
563     !                                                                      !
564     !  Purpose: Take a string containing a species alias and stoichio-     !
565     !  metric coefficient and splits them into their respective parts.     !
566     !                                                                      !
567     !  If no numerical coefficient is found, it is set to one.             !
568     !                                                                      !
569     !  If present, asterisks (*) are assumed to seperate numerical         !
570     !  coefficients and the species alias. If more than one asterisk is    !
571     !  found, and error is reported and MFIX_EXIT is called.               !
572     !                                                                      !
573     !  Variables referenced: None                                          !
574     !                                                                      !
575     !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
576           SUBROUTINE splitAliasAndCoeff(lName, lChemEq, lStart, lEnd,      &
577              lAlias, lCoeff)
578     
579           IMPLICIT NONE
580     
581     ! Pass Arguments:
582     !---------------------------------------------------------------------//
583     ! Chemical reaction name.
584           CHARACTER(len=*), INTENT(IN) :: lName
585     ! Chemical Equation.
586           CHARACTER(len=*), INTENT(IN) :: lChemEq
587     ! Starting position for substring analysis.
588           INTEGER, INTENT(IN) :: lStart
589     ! Ending position for substring analysis.
590           INTEGER, INTENT(IN) :: lEnd
591     ! Species Aliases from the chemical equation.
592           CHARACTER(LEN=32), INTENT(OUT) :: lAlias
593     ! Stoichiometric coefficient pulled from the chemical equation.
594           DOUBLE PRECISION, INTENT(OUT) :: lCoeff
595     
596     ! Local Variables:
597     !---------------------------------------------------------------------//
598     ! Flag
599           LOGICAL MATCH
600           INTEGER nPOS
601     
602           INTEGER L, N, IOS, aPOS, a2POS
603     
604           CHARACTER(LEN=12), PARAMETER :: Numbers = '.0123456789'
605     
606     ! A flag generated to point out the location of the entry error.
607           CHARACTER(LEN=512) FLAG
608           FLAG = ''
609     
610     ! Locate the first asterisk (if any). Search left-to-right.
611           aPOS = INDEX(lChemEq(lStart:lEnd),"*", BACK=.FALSE.)
612     ! An asterisk was found.
613           IF(aPOS .GT. ZERO) THEN
614     ! Make sure that there isn't another asterisk further down the string.
615              a2POS = INDEX(lChemEq(lStart:lEnd),"*", BACK=.TRUE.)
616              IF(aPOS /= a2POS) THEN
617                 IF(myPE == PE_IO) THEN
618     ! Construct the error flag.
619                    FLAG = setFlag(20, lStart+aPOS, lStart+a2POS)
620     ! Write the message to the screen.
621                    write(*,1000) trim(lName)
622                    write(*,1002)'Too many'
623                    write(*,1010) trim(lChemEq), trim(Flag)
624                    write(*,1001)
625     ! Write message to log file.
626                    write(UNIT_LOG,1000) trim(lName)
627                    write(UNIT_LOG,1002)'Too many'
628                    write(UNIT_LOG,1010) trim(lChemEq), trim(Flag)
629                    write(UNIT_LOG,1001)
630     ! Exit MFIX
631                    CALL MFIX_EXIT(myPE)
632                 ENDIF
633              ELSE
634     ! Store left-of-asterisk as the coefficient. If an error occurs in
635     ! converting the string to double precision, flag the problem and
636     ! call MFIX_EXIT.
637                 READ(lChemEq(lStart:(lStart+aPOS-2)),*,IOSTAT=IOS) lCoeff
638                 IF(IOS .NE. 0 .AND. myPE == PE_IO) THEN
639     ! Construct the error flag.
640                    FLAG = setFlag(20, lStart + int(aPOS/2))
641     ! Write the message to the screen.
642                    write(*,1000) trim(lName)
643                    write(*,1010) trim(lChemEq), trim(Flag)
644                    write(*,1001)
645     ! Write message to log file.
646                    write(UNIT_LOG,1000) trim(lName)
647                    write(UNIT_LOG,1010) trim(lChemEq), trim(Flag)
648                    write(UNIT_LOG,1001)
649     ! Exit MFIX
650                    CALL MFIX_EXIT(myPE)
651                 ENDIF
652     ! Store right-of-asterisk as the species alias.
653                 WRITE(lAlias,"(A)") &
654                    trim(adjustl(lChemEq((lStart+aPOS):lEnd)))
655              ENDIF
656     ! If no asterisk was found, search for numbers and spaces.
657           ELSE
658     ! Initialize the position of last consecutive number.
659              nPOS = 0
660     ! In a left-to-right search, check if the characters in the entry are
661     ! numbers or punctuation.
662              DO L=lStart,lEnd
663                 MATCH = .FALSE.
664                 DO N=1,12
665                    IF(lChemEq(L:L) /= Numbers(N:N)) CYCLE
666     ! Note the position of the number.
667                    nPOS = L
668     ! Flag that a match was made.
669                    MATCH = .TRUE.
670                 ENDDO
671     ! If no match, assume the end of the coefficient was found.
672                 IF(.NOT.MATCH) EXIT
673              ENDDO
674     ! If no numbers or punctuation was found, assumed the stoichiometric
675     ! coefficient is one.
676              IF(trim(lChemEq(lStart:nPOS)) =='') THEN
677                 lCoeff = 1.0d0
678              ELSE
679     ! If leading numbers were found, store as the stoich-coeff.
680                 READ(lChemEq(lStart:nPOS),*,IOSTAT=IOS) lCoeff
681     ! Report any problems in converting the string to double precision.
682                 IF(IOS .NE. 0 .AND. myPE == PE_IO) THEN
683     ! Construct the error flag.
684                    FLAG = setFlag(20, &
685                       lStart+int(len_trim(lChemEq(lStart:nPOS))/2))
686     ! Write the message to the screen.
687                    write(*,1000) trim(lName)
688                    write(*,1010) trim(lChemEq), trim(Flag)
689                    write(*,1001)
690     ! Write message to log file.
691                    write(UNIT_LOG,1000) trim(lName)
692                    write(UNIT_LOG,1010) trim(lChemEq), trim(Flag)
693                    write(UNIT_LOG,1001)
694     ! Exit MFIX
695                    CALL MFIX_EXIT(myPE)
696                 ENDIF
697              ENDIF
698     ! Store right-of-coefficient as the species alias.
699              READ(lChemEq(nPOS+1:lEnd),*,IOSTAT=IOS) lAlias
700           ENDIF
701     ! Quick check to make sure that the species alias is not empty.
702           IF(LEN_TRIM(lAlias) == 0 .AND. myPE == PE_IO) THEN
703     ! Construct the error flag.
704              FLAG = setFlag(20, lStart + int(lEnd/2))
705     ! Write the message to the screen.
706              write(*,1003) trim(lName)
707              write(*,1010) trim(lChemEq), trim(Flag)
708              write(*,1001)
709     ! Write message to log file.
710              write(UNIT_LOG,1003) trim(lName)
711              write(UNIT_LOG,1010) trim(lChemEq), trim(Flag)
712              write(UNIT_LOG,1001)
713     ! Exit MFIX
714              CALL MFIX_EXIT(myPE)
715           ENDIF
716     
717           RETURN
718     
719      1000 FORMAT(/1X,70('*')/' From: From: setReaction -->',               &
720              ' splitAliasAndCoeff',/' Message: Error determining the',     &
721              ' stoichiometric coefficient in the',/' chemical equation',   &
722              ' for reaction ',A,'.')
723     
724     
725      1001 FORMAT(' Please refer to the Readme file for chemical equation', &
726              ' input formats',/' and correct the data file.',/1X,70('*')/)
727     
728      1002 FORMAT(/1X,A,' operators were found!')
729     
730      1003 FORMAT(/1X,70('*')/' From: From: setReaction -->',               &
731              ' splitAliasAndCoeff',/' Message: Error determining the',     &
732              ' speices in the chemical equation for',/' reaction ',A,'.'/)
733     
734      1010 FORMAT(/' Chemical Equation: ',A,/1X, A/)
735     
736      1011 FORMAT(/' Chemical Equation: ',A,/)
737     
738           END SUBROUTINE splitAliasAndCoeff
739     
740     !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
741     !  Function name: checkBlankAliases()                                  !
742     !                                                                      !
743     !  Purpose: Take a string containing a species alias and stoichio-     !
744     !  metric coefficient and splits them into their respective parts.     !
745     !                                                                      !
746     !  Variables referenced: None                                          !
747     !                                                                      !
748     !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
749           SUBROUTINE checkBlankAliases(lNg, lSAg, lM, lNs, lSAs, lBA)
750     
751           IMPLICIT NONE
752     
753     ! Number of gas speices
754           INTEGER, INTENT(IN) :: lNg
755     ! Gas phase species aliases
756           CHARACTER(len=32), DIMENSION(DIM_N_g), INTENT(IN) :: lSAg
757     ! Number of solids phases
758           INTEGER, INTENT(IN) :: lM
759     ! Number of species in each solids phase.
760           INTEGER, DIMENSION(DIM_M), INTENT(IN) :: lNs
761     ! Solids phase speices aliases.
762           CHARACTER(len=32), DIMENSION(DIM_M, DIM_N_s), INTENT(IN) :: lSAs
763     
764           LOGICAL, INTENT(OUT) :: lBA(0:(DIM_N_g + lM*DIM_N_s))
765     
766           INTEGER M, N
767     
768     ! Loop counter for continuum and discrete species
769           INTEGER Nsp
770     
771     ! Initialize counters
772           Nsp = 0
773     
774           lBA(0) = .FALSE.
775           DO N = 1, lNg
776              Nsp = Nsp + 1
777              lBA(Nsp) = .FALSE.
778              IF(len_trim(lSAg(N)) == 0) THEN
779                 lBA(Nsp) = .TRUE.
780                 lBA(0) = .TRUE.
781              ENDIF
782           ENDDO
783     
784     ! Compare aliaes between solids phases
785           DO M = 1, lM
786              DO N = 1, lNs(M)
787                 Nsp = Nsp + 1
788                 lBA(Nsp) = .FALSE.
789                 IF(len_trim(lSAs(M,N)) == 0) THEN
790                    lBA(Nsp) = .TRUE.
791                    lBA(0) = .TRUE.
792                 ENDIF
793              ENDDO
794           ENDDO
795     
796           RETURN
797           END SUBROUTINE checkBlankAliases
798     
799     !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
800     !  Function name: mapAliases()                                         !
801     !                                                                      !
802     !  Purpose: Take a string containing a species alias and stoichio-     !
803     !  metric coefficient and splits them into their respective parts.     !
804     !                                                                      !
805     !  If no numerical coefficient is found, it is set to one.             !
806     !                                                                      !
807     !  If present, asterisks (*) are assumed to seperate numerical         !
808     !  coefficients and the species alias. If more than one asterisk is    !
809     !  found, and error is reported and MFIX_EXIT is called.               !
810     !                                                                      !
811     !  Variables referenced: None                                          !
812     !                                                                      !
813     !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
814           SUBROUTINE mapAliases(lName, lChemEq, lNg, lSAg, lM, lNs, lSAs,  &
815              lNo, lAlias, lCoeff, lSgn, lStart, lBA, lRxN)
816     
817           use rxn_com
818     
819           IMPLICIT NONE
820     
821     ! Pass Arguments:
822     !---------------------------------------------------------------------//
823     ! Chemical reaction name.
824           CHARACTER(len=*), INTENT(IN) :: lName
825     ! Chemical Equation.
826           CHARACTER(len=*), INTENT(IN) :: lChemEq
827     ! Number of gas speices
828           INTEGER, INTENT(IN) :: lNg
829     ! Gas phase species aliases
830           CHARACTER(len=32), DIMENSION(DIM_N_g), INTENT(IN) :: lSAg
831     ! Number of solids phases
832           INTEGER, INTENT(IN) :: lM
833     ! Number of species in each solids phase.
834           INTEGER, DIMENSION(DIM_M), INTENT(IN) :: lNs
835     ! Solids phase speices aliases.
836           CHARACTER(len=32), DIMENSION(DIM_M, DIM_N_s), INTENT(IN) :: lSAs
837     ! Number of products (or reactants)
838           INTEGER, INTENT(IN) :: lNo
839     ! Species Alaises pulled from the chemical equation.
840           CHARACTER(LEN=32), DIMENSION(50), INTENT(IN) :: lAlias
841     
842           DOUBLE PRECISION, DIMENSION(50), INTENT(IN) :: lCoeff
843     
844           DOUBLE PRECISION, INTENT(IN) :: lSgn
845     
846           INTEGER, INTENT(IN) :: lStart
847     
848           LOGICAL, INTENT(IN) :: lBA(0:(DIM_N_g + lM*DIM_N_s))
849     
850     ! Data structure for storing reaction data.
851           TYPE(REACTION_BLOCK), POINTER, INTENT(INOUT) :: lRxN
852     
853     
854     ! Local Variables:
855     !---------------------------------------------------------------------//
856     ! Loop counters.
857           INTEGER L, M, NN
858     ! A flag generated to point out the location of the entry error.
859           CHARACTER(LEN=512) FLAG
860     ! Location in string to locate error.
861           INTEGER lPOS, rPOS
862     
863     ! Initialize the error flag.
864           FLAG = ''
865     
866     ! Loop over the number of (reactants/products)
867           ALOOP : DO L=1, lNo
868     ! Compare entry with gas phase species.
869              DO NN = 1, lNg
870                 IF( checkMatch(lSAg(NN), lAlias(L))) THEN
871                    lRxN%Species(lStart + L)%pMap = 0
872                    lRxN%Species(lStart + L)%sMap = NN
873                    lRxN%Species(lStart + L)%Coeff = lSgn * lCoeff(L)
874                    CYCLE ALOOP
875                 ENDIF
876              ENDDO
877     ! Compare entry with solids phase species.
878              DO M = 1, lM
879                 DO NN = 1, lNs(M)
880                    IF(checkMatch(lSAs(M,NN),lAlias(L))) THEN
881                       lRxN%Species(lStart + L)%pMap = M
882                       lRxN%Species(lStart + L)%sMap = NN
883                       lRxN%Species(lStart + L)%Coeff = lSgn * lCoeff(L)
884                       CYCLE ALOOP
885                    ENDIF
886                 ENDDO
887              ENDDO
888     ! No matching species was located. Flag an error and exit.
889              IF(myPE == PE_IO) THEN
890     ! Construct the error flag.
891                 lPOS = INDEX(lChemEq,trim(lAlias(L)), BACK=.FALSE.)
892                 rPOS = INDEX(lChemEq,trim(lAlias(L)), BACK=.TRUE.)
893                 FLAG = setFlag(20, 1 + int((lPOS + rPOS)/2))
894     ! Write the message to the screen.
895                 write(*,1000) trim(lAlias(L)), trim(lName)
896                 write(*,1010) trim(lChemEq), trim(Flag)
897                 IF(lBA(0)) CALL writeBA()
898                 write(*,1001)
899     ! Write message to log file.
900                 write(UNIT_LOG,1000) trim(lAlias(L)), trim(lName)
901                 write(UNIT_LOG,1010) trim(lChemEq), trim(Flag)
902                 IF(lBA(0)) CALL writeBA(UNIT_LOG)
903                 write(UNIT_LOG,1001)
904              ENDIF
905     ! Exit MFIX
906              CALL MFIX_EXIT(myPE)
907     
908           ENDDO ALOOP
909     
910           RETURN
911     
912      1000 FORMAT(/1X,70('*')/' From: From: setReaction --> mapAliases',/   &
913              ' Message: Unable to match species ',A,' in the chemical',    &
914              ' equation for ',/' reaction ',A,'.')
915     
916      1001 FORMAT(/' Please refer to the Readme file for chemical equation',&
917              ' input formats',/' and correct the data file.',/1X,70('*')/)
918     
919      1010 FORMAT(/' Chemical Equation: ',A,/1X, A/)
920     
921      1011 FORMAT(/' Chemical Equation: ',A,/)
922     
923     
924           contains
925     
926     !......................................................................!
927     !  Function name: checkMatch                                           !
928     !                                                                      !
929     !  Purpose: Takes two species aliases as arguments, converts them to   !
930     !  uppercase and checks if they match.                                 !
931     !                                                                      !
932     !  Variables referenced: None                                          !
933     !                                                                      !
934     !......................................................................!
935           LOGICAL FUNCTION checkMatch(lSA, ceSA)
936     
937           IMPLICIT NONE
938     
939     ! Pass Arguments:
940     !---------------------------------------------------------------------//
941           CHARACTER(LEN=32), INTENT(IN) :: lSA, ceSA
942     
943     ! Local Variables:
944     !---------------------------------------------------------------------//
945           CHARACTER(LEN=32) tlSA
946     
947     ! Copy species alias.
948           tlSA = lSA
949     ! Remove case sensitivity.
950           CALL MAKE_UPPER_CASE (tlSA,32)
951     ! Compare the two strings.
952           checkMatch = .FALSE.
953           IF(trim(tlSA) == trim(ceSA)) checkMatch = .TRUE.
954           RETURN
955           END FUNCTION checkMatch
956     
957     !......................................................................!
958     !  Function name: updateMap                                            !
959     !                                                                      !
960     !  Purpose: Flags that the passed phase is part of the chemical        !
961     !  reaction. If the phase was not already noted, the number of phases  !
962     !  in the reaction is increased and the flag set true. Additionally,   !
963     !  The number of species (either product or reactant) for the phase    !
964     !  is incremented.                                                     !
965     !                                                                      !
966     !  Variables referenced: None                                          !
967     !                                                                      !
968     !......................................................................!
969           SUBROUTINE updateMap(lnP, lpMap, llNoP)
970     
971           IMPLICIT NONE
972     
973     ! Pass Arguments:
974     !---------------------------------------------------------------------//
975           INTEGER, INTENT(INOUT) :: lnP
976     ! Map of phases for the reaction.
977           LOGICAL, INTENT(INOUT) :: lpMap
978           INTEGER, INTENT(INOUT) :: llNoP
979     
980     ! Local Variables:
981     !---------------------------------------------------------------------//
982     ! None
983     
984     ! Increment the number of reactants/products this phase has involved in
985     ! the current reaction.
986           llNoP = llNoP + 1
987     ! If the phase was already identified, return.
988           IF(lpMap) RETURN
989     ! If this is the first time the phase is identififed, set the flag to
990     ! true and increment the total number of phases in the reaction.
991           lnP = lnP + 1
992           lpMap = .TRUE.
993     
994           RETURN
995           END SUBROUTINE updateMap
996     
997     
998     !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
999     !  Function name: writeBA()                                            !
1000     !                                                                      !
1001     !  Purpose: Print out which species were not given aliases.            !
1002     !                                                                      !
1003     !  Variables referenced: None                                          !
1004     !                                                                      !
1005     !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
1006           SUBROUTINE writeBA(FUNIT)
1007     
1008           IMPLICIT NONE
1009     
1010     ! File unit
1011           INTEGER, OPTIONAL, INTENT(IN) :: FUNIT
1012     
1013           INTEGER M, N
1014     
1015     ! Loop counter for continuum and discrete species
1016           INTEGER Nsp
1017     
1018           IF(.NOT.PRESENT(FUNIT)) THEN
1019              write(*,1000)
1020           ELSE
1021              write(FUNIT,1000)
1022           ENDIF
1023     
1024     ! Initialize counters
1025           Nsp = 0
1026     
1027           DO N = 1, lNg
1028              Nsp = Nsp + 1
1029              IF(lBA(Nsp)) THEN
1030                 IF(.NOT.PRESENT(FUNIT)) THEN
1031                    write(*,1001)N
1032                 ELSE
1033                    write(FUNIT,1001) N
1034                 ENDIF
1035              ENDIF
1036           ENDDO
1037     
1038     ! Compare aliaes between solids phases
1039           DO M = 1, lM
1040              DO N = 1, lNs(M)
1041                 Nsp = Nsp + 1
1042     
1043                 IF(lBA(Nsp)) THEN
1044                    IF(.NOT.PRESENT(FUNIT)) THEN
1045                       write(*,1002)M, N
1046                    ELSE
1047                       write(FUNIT,1002)M, N
1048                    ENDIF
1049                 ENDIF
1050              ENDDO
1051           ENDDO
1052     
1053           RETURN
1054     
1055      1000 FORMAT(' Species aliases were not provided for the following:')
1056      1001 FORMAT(3X, ' Gas phase species ',I2)
1057      1002 FORMAT(3X, ' Solid phase ',I2,' specie ',I2)
1058     
1059           END SUBROUTINE writeBA
1060     
1061           END SUBROUTINE mapAliases
1062     
1063     
1064     !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
1065     !  Function name: setFlag                                              !
1066     !                                                                      !
1067     !  Purpose: Creates a flag pointing to a particular string location.   !
1068     !                                                                      !
1069     !  Variables referenced: None                                          !
1070     !                                                                      !
1071     !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
1072           CHARACTER(len=512) FUNCTION setFlag(fill, flg1, flg2) RESULT(OUT)
1073     
1074           IMPLICIT NONE
1075     
1076     ! Pass Arguments:
1077     !---------------------------------------------------------------------//
1078     ! Number of leading spaces to fill with dashes. This is used to jump
1079     ! past any lead-in text.
1080           INTEGER, INTENT(IN) :: fill
1081     ! Location in string to place the pointer.
1082           INTEGER, INTENT(IN) :: flg1
1083     ! Optional - location of second pointer in string
1084           INTEGER, INTENT(IN), OPTIONAL :: flg2
1085     
1086     ! Local Variables:
1087     !---------------------------------------------------------------------//
1088           INTEGER L, FILL1, FILL2
1089     
1090     ! Create a string with "FILL" dash characters.
1091           OUT = ''
1092           DO L = 1, FILL-1
1093              WRITE(OUT,"(A,A)") trim(OUT), '-'
1094           ENDDO
1095     
1096     ! If a second pointer is present, determined the larger of the two.
1097           IF(PRESENT(flg2)) THEN
1098              IF(flg1 < flg2) THEN
1099                 FILL1 = flg1 - 1
1100                 FILL2 = (flg2-flg1) - 1
1101              ELSE
1102                 FILL1 = flg2 - 1
1103                 FILL2 = (flg1-flg2) - 1
1104              ENDIF
1105           ELSE
1106              FILL1 = flg1 - 1
1107              FILL2 = 0
1108           ENDIF
1109     
1110     ! Fill with dashes up to the the first pointer. ----^
1111           DO L = 1, FILL1
1112              WRITE(OUT,"(A,A)") trim(OUT), '-'
1113           ENDDO
1114           WRITE(OUT,"(A,A)") trim(OUT), '^'
1115     ! Fill with dashes up to the second pointer. ----^---^
1116           IF(FILL2 > 0) THEN
1117              DO L = 1, FILL2
1118                 WRITE(OUT,"(A,A)") trim(OUT), '-'
1119              ENDDO
1120              WRITE(OUT,"(A,A)") trim(OUT), '^'
1121           ENDIF
1122     
1123           END FUNCTION setFlag
1124     
1125     END MODULE parse
1126