Index: LMDZ6/branches/LMDZ-tracers/libf/misc/readTracFiles_mod.f90
===================================================================
--- LMDZ6/branches/LMDZ-tracers/libf/misc/readTracFiles_mod.f90	(revision 3957)
+++ LMDZ6/branches/LMDZ-tracers/libf/misc/readTracFiles_mod.f90	(revision 3985)
@@ -106,5 +106,5 @@
 
   !--- TELLS WHAT WAS IS ABOUT TO BE USED
-  IF(test(fmsg(fType==0, 'No adequate tracers description file(s) found ; default values will be used'), lerr)) RETURN
+  IF( fmsg(fType==0, 'No adequate tracers description file(s) found ; default values will be used')) RETURN
   CALL msg(fType==1, 'Trying to read old-style tracers description file "traceur.def"')
   CALL msg(fType==2, 'Trying to read the new style multi-sections tracers description file "tracer.def"')
@@ -860,10 +860,11 @@
     !--- REDUCE THE EXPRESSIONS TO OBTAIN SCALARS AND TRANSFER THEM TO THE "isot" ISOTOPES DESCRIPTORS VECTOR
     DO it = 1, SIZE(dBase(idb)%trac)
-      is = strIdx(isot(iis)%keys(:)%name, dBase(idb)%trac(it)%name)  !--- Index of the "isot(iis)%keys(:)%name" tracer named "t%name"
+      t => dBase(idb)%trac(it)
+      is = strIdx(isot(iis)%keys(:)%name, t%name)                    !--- Index in "isot(iis)%keys(:)%name" of isotope "t%name"
       IF(is == 0) CYCLE
-      t => dBase(idb)%trac(it)
       liso = reduceExpr(t%keys%val, vals)                            !--- Reduce expressions (for substituted variables)
-      isot(iis)%keys(is)%key = PACK(t%keys%key, MASK=liso)
-      isot(iis)%keys(is)%val = PACK(  vals,     MASK=liso)
+      IF(test(ANY(liso), lerr)) RETURN                               !--- Some non-numerical elements were found
+      isot(iis)%keys(is)%key = PACK(t%keys%key, MASK=.NOT.liso)
+      isot(iis)%keys(is)%val = PACK(  vals,     MASK=.NOT.liso)
     END DO
 
@@ -1228,12 +1229,16 @@
 ELEMENTAL CHARACTER(LEN=256) FUNCTION delPhase(s) RESULT(out)
   CHARACTER(LEN=*), INTENT(IN) :: s
-  INTEGER :: l, i
+  INTEGER :: l, i, ix
   out = s
-  IF(s == '') RETURN
-  i = INDEX(s, '_'); l = LEN_TRIM(s)
-  IF(i == 0) THEN
-    IF(s(l-1:l-1)==phases_sep .AND. INDEX(known_phases,s(l:l)) /= 0) out = s(1:l-2)
-  ELSE; i=i-1
-    IF(s(i-1:i-1)==phases_sep .AND. INDEX(known_phases,s(i:i)) /= 0) out = s(1:i-2)//s(i+1:l)
+  IF(s == '') RETURN                                                           !--- Empty string: nothing to do
+  !--- Index of found phase in "known_phases"
+  ix = MAXLOC( [(i, i=1,nphases)], MASK=[( INDEX(s, phases_sep//known_phases(i:i))/=0, i=1, nphases)], DIM=1 )
+  IF(ix == 0) RETURN                                                           !--- No phase pattern found
+  i = INDEX(s, phases_sep//known_phases(ix:ix))                                !--- Index of <sep><pha> pattern in "str"
+  l = LEN_TRIM(s)
+  IF(i == l-1) THEN                                                            !--- <var><sep><pha>       => return <var>
+    out = s(1:l-2)
+  ELSE IF(s(i+2:i+2) == '_') THEN                                              !--- <var><sep><pha>_<tag> => return <var>_<tag>
+    out = s(1:i-1)//s(i+2:l)
   END IF
 END FUNCTION delPhase
@@ -1244,8 +1249,9 @@
   INTEGER :: l, i
   out = s
-  IF(s == '') RETURN
-  i = INDEX(s, '_'); l = LEN_TRIM(s)
-  IF(i == 0) out =  TRIM(s)//phases_sep//pha
-  IF(i /= 0) out = s(1:i-1)//phases_sep//pha//'_'//s(i+1:l)
+  IF(s == '') RETURN                                                           !--- Empty string: nothing to do
+  i = INDEX(s, '_')                                                            !--- /=0 for <var>_<tag> tracers names
+  l = LEN_TRIM(s)
+  IF(i == 0) out =  TRIM(s)//phases_sep//pha                                   !--- <var>       => return <var><sep><pha>
+  IF(i /= 0) out = s(1:i-1)//phases_sep//pha//'_'//s(i+1:l)                    !--- <var>_<tag> => return <var><sep><pha>_<tag>
 END FUNCTION addPhase_1
 !------------------------------------------------------------------------------------------------------------------------------
Index: LMDZ6/branches/LMDZ-tracers/libf/misc/strings_mod.F90
===================================================================
--- LMDZ6/branches/LMDZ-tracers/libf/misc/strings_mod.F90	(revision 3957)
+++ LMDZ6/branches/LMDZ-tracers/libf/misc/strings_mod.F90	(revision 3985)
@@ -187,4 +187,7 @@
 !==============================================================================================================================
 !=== Extract the substring in front of the last (first if lFirst==TRUE) occurrence of separator "sep" in "str" ================
+!=== Examples for str='a_b_c' and sep='_' and the bash command with the same effect:                           ================
+!===    * strHead(..,.FALSE.) = 'a'           ${str%%$sep*}                                                    ================
+!===    * strHead(..,.TRUE.)  = 'a_b'         ${str%$sep*}                                                     ================
 !==============================================================================================================================
 CHARACTER(LEN=256) FUNCTION strHead_1(str,sep,lFirst) RESULT(out)
@@ -215,8 +218,10 @@
     out = [(strHead_1(str(k),lFirst=.NOT.lf), k=1, SIZE(str))]
   END IF
-
 END FUNCTION strHead_m
 !==============================================================================================================================
-!=== Extract the substring following the last (first if lFirst==TRUE) occurrence of separator "sep" in "str" ==================
+!=== Extract the substring following the last (first if lFirst==TRUE) occurrence of separator "sep" in "str"   ================
+!=== Examples for str='a_b_c' and sep='_' and the bash command with the same effect:                           ================
+!===    * strHead(..,.FALSE.) = 'b_c'         ${str#*$sep}                                                     ================
+!===    * strHead(..,.TRUE.)  = 'c'           ${str##*$sep}                                                    ================
 !==============================================================================================================================
 CHARACTER(LEN=256) FUNCTION strTail_1(str,sep,lFirst) RESULT(out)
@@ -430,4 +435,5 @@
   LOGICAL, OPTIONAL, INTENT(IN)  :: lSc                              !--- Care about nbs with front sign or in scient. notation
 
+  INTEGER              :: idx0                                       !--- Used to display an identified non-numeric string
   INTEGER, ALLOCATABLE :: ii(:)
   LOGICAL              :: ll, ls
@@ -435,25 +441,29 @@
 !  modname = 'strIdx'
   lerr = .FALSE.
-  idx = strIdx1(rawList, del, ibeg, idel)
-  IF(.NOT.PRESENT(lSc))                     RETURN                  !--- No need to check exceptions for numbers => finished
-  IF(.NOT.        lSc )                     RETURN                  !--- No need to check exceptions for numbers => finished
+  idx = strIdx1(rawList, del, ibeg, idel)                            !--- del(idel) appears in "rawList" at position idx
+  IF(.NOT.PRESENT(lSc))               RETURN                         !--- No need to check exceptions for numbers => finished
+  IF(.NOT.        lSc )               RETURN                         !--- No need to check exceptions for numbers => finished
+  IF(idx == 0) THEN                                                  !--- No element of "del" in "rawList":
+    lerr = .NOT.is_numeric(rawList(ibeg:))                           !--- String must be a number
+    IF(lerr) idx = LEN_TRIM(rawList); RETURN                         !--- Update idx => rawList(ibeg:idx-1) is the whole string
+  END IF
+  idx0 = idx
+  IF(test(idx==1.AND.INDEX('+-',del(idel))/=0, lerr)) RETURN         !--- Front separator different from +/-: error
+  IF(idx/=1.AND.is_numeric(rawList(ibeg:idx-1)))      RETURN         !--- The input string tail is a valid number
+  idx = strIdx1(rawList, del, idx+1, idel)                           !---   => TO THE NEXT DELIMITER
   IF(idx == 0) THEN
-    lerr = .NOT.is_numeric(rawList(ibeg:)); RETURN                  !--- No separator detected: string must be a number
-  END IF
-  IF(test(idx==1.AND.INDEX('+-',del(idel))/=0, lerr)) RETURN        !--- Front separator different from +/-: error
-  IF(is_numeric(rawList(ibeg:idx-1)))                 RETURN        !--- The input string tail is a valid number
-  idx = strIdx1(rawList, del, idx+1, idel)                          !---   => TO THE NEXT DELIMITER
+    lerr = .NOT.is_numeric(rawList(ibeg:))                           !--- No delimiter detected: string must be a number
+    IF(lerr) idx = idx0; RETURN
+  END IF
+  idx0 = idx
+  IF(is_numeric(rawList(ibeg:idx-1)))                 RETURN         !--- The input string tail is a valid number
+  IF(test(          INDEX('eE',rawList(idx-1:idx-1)) /= 0  &         !--- Sole possible exception: scientific notation: E+/-
+               .OR. INDEX('+-',del(idel)) /=0, lerr)) RETURN
+  idx = strIdx1(rawList, del, idx+1, idel)                           !---   => TO THE NEXT DELIMITER
   IF(idx == 0) THEN
-    lerr = .NOT.is_numeric(rawList(ibeg:)); RETURN                  !--- No separator detected: string must be a number
-  END IF
-  IF(is_numeric(rawList(ibeg:idx-1)))                 RETURN        !--- The input string tail is a valid number
-  IF(test(          INDEX('eE',rawList(idx-1:idx-1)) /= 0  &        !--- Sole possible exception: scientific notation: E+/-
-               .OR. INDEX('+-',del(idel)) /=0, lerr)) RETURN
-  idx = strIdx1(rawList, del, idx+1, idel)                          !---   => TO THE NEXT DELIMITER
-  IF(idx == 0) THEN
-    lerr = .NOT.is_numeric(rawList(ibeg:)); RETURN                  !--- No separator detected: string must be a number
+    lerr = .NOT.is_numeric(rawList(ibeg:))                           !--- No separator detected: string must be a number
+    IF(lerr) idx = idx0; RETURN
   END IF
   lerr = .NOT.is_numeric(rawList(ibeg:idx-1))
-
 CONTAINS
 
@@ -538,6 +548,6 @@
   DO
     lerr = strIdx_prv(r, delimiter, ib, ie, jd, ll)
+    IF(fmsg(lerr,'"'//TRIM(r(ib:ie-1))//'" is not numeric')) RETURN
     IF(jd == 0) EXIT
-    IF(fmsg(lerr,'"'//TRIM(r(ib:ie-1))//'" is not numeric')) RETURN
     ib = ie + LEN(delimiter(jd))
     DO WHILE(r(ib:ib) == ' ' .AND. ib < nr); ib = ib + 1; END DO     !--- Skip spaces before next chain
@@ -1117,5 +1127,5 @@
 !=== Reduce an algebrical expression (basic operations and parenthesis) to a single number (string format) ====================
 !==============================================================================================================================
-LOGICAL FUNCTION reduceExpr_1(str, val) RESULT(out)
+LOGICAL FUNCTION reduceExpr_1(str, val) RESULT(lerr)
   CHARACTER(LEN=*),    INTENT(IN)  :: str
   CHARACTER(LEN=256),  INTENT(OUT) :: val
@@ -1133,6 +1143,6 @@
   ll = strCount(s,'(',nl)
   ll = strCount(s,')',nn)
-  out = nl == nn
-  IF(fmsg(.NOT.out, 'Mismatching number of opening and closing parenthesis: '//TRIM(s))) RETURN
+  lerr = nl /= nn
+  IF(fmsg(lerr, 'Mismatching number of opening and closing parenthesis: '//TRIM(s))) RETURN
   nl = 2*nl-1
 
@@ -1152,5 +1162,5 @@
   DO WHILE(nl > 1)
     i = 1; DO WHILE(ip(i) /= 1 .OR. ip(i+1) /= 2); i = i + 1; END DO !IF(i > SIZE(ip)+1) EXIT;END DO
-    out = reduceExpr_basic(vl(i+1), v); IF(.NOT. out) RETURN
+    IF(test(reduceExpr_basic(vl(i+1), v), lerr)) RETURN
     v = TRIM(vl(i))//TRIM(v); IF(i+2<=nl) v=TRIM(v)//TRIM(vl(i+2))
     vv = v//REPEAT(' ',768)
@@ -1160,5 +1170,5 @@
     nl = SIZE(vl)
   END DO
-  out = reduceExpr_basic(vl(1), val)
+  lerr = reduceExpr_basic(vl(1), val)
 END FUNCTION reduceExpr_1
 
@@ -1167,5 +1177,5 @@
 !=== Reduce a simple algebrical expression (basic operations, no parenthesis) to a single number (string format) ==============
 !==============================================================================================================================
-LOGICAL FUNCTION reduceExpr_basic(str, val) RESULT(out)
+LOGICAL FUNCTION reduceExpr_basic(str, val) RESULT(lerr)
   CHARACTER(LEN=*),   INTENT(IN)  :: str
   CHARACTER(LEN=*),   INTENT(OUT) :: val
@@ -1178,15 +1188,14 @@
   DOUBLE PRECISION :: v, vm, vp
   INTEGER      :: i, ni, io
-  LOGICAL :: ll
 
 !  modname = 'reduceExpr_basic'
-  out = .TRUE.
+  lerr = .FALSE.
   IF(is_numeric(str)) THEN; val=TRIM(str); RETURN; END IF
   op = ['^','/','*','+','-']                                                   !--- List of recognized operations
   s = str
-  ll = strParse_m(s, op, ky, .TRUE., id = id)                                  !--- Parse the values
+  IF(test(strParse_m(s, op, ky, .TRUE., id = id), lerr)) RETURN                !--- Parse the values
   vl = str2dble(ky)                                                            !--- Conversion to doubles
-  out = ALL(vl < HUGE(1.d0))
-  IF(fmsg(.NOT.out,'Some values are non-numeric in: '//TRIM(s))) RETURN        !--- Non-numerical values found
+  lerr = ANY(vl >= HUGE(1.d0))
+  IF(fmsg(lerr,'Some values are non-numeric in: '//TRIM(s))) RETURN            !--- Non-numerical values found
   DO io = 1, SIZE(op)                                                          !--- Loop on known operators (order matters !)
     DO i = SIZE(id), 1, -1                                                     !--- Loop on found operators
@@ -1211,11 +1220,11 @@
 
 !==============================================================================================================================
-FUNCTION reduceExpr_m(str, val) RESULT(out)
-  LOGICAL,            ALLOCATABLE              :: out(:)
+FUNCTION reduceExpr_m(str, val) RESULT(lerr)
+  LOGICAL,            ALLOCATABLE              :: lerr(:)
   CHARACTER(LEN=*),                INTENT(IN)  :: str(:)
   CHARACTER(LEN=256), ALLOCATABLE, INTENT(OUT) :: val(:)
   INTEGER :: i
-  ALLOCATE(out(SIZE(str)),val(SIZE(str)))
-  out(:) = [(reduceExpr_1(str(i), val(i)), i=1, SIZE(str))]
+  ALLOCATE(lerr(SIZE(str)),val(SIZE(str)))
+  lerr(:) = [(reduceExpr_1(str(i), val(i)), i=1, SIZE(str))]
 END FUNCTION reduceExpr_m
 !==============================================================================================================================
@@ -1230,4 +1239,5 @@
   INTEGER :: e
   CHARACTER(LEN=12) :: fmt
+  IF(TRIM(str) == '') THEN; out = .FALSE.; RETURN; END IF
   WRITE(fmt,'("(f",i0,".0)")') LEN_TRIM(str)
   READ(str,fmt,IOSTAT=e) x
