Changeset 5183 for LMDZ6/trunk/libf/misc


Ignore:
Timestamp:
Sep 10, 2024, 5:14:23 PM (5 months ago)
Author:
dcugnet
Message:
  • Remove INCA retro-compatibility with "traceur.def" (containing only water tracers but getting chemical species from an internal INCA routine).
  • The "trac_type" derived type internal to "readTracFiles_mod" is removed because a generic "keys_type" is enough: no explicit key ("%" operator) is needed, even %name.
  • The "trac_type" and "isot_type" derived types are now defined locally in "infotrac" and "infotrac_phy" (and more generally in each context: dynamic, lmdz dynamics, lmdz physics, etc.). The "readTracFiles_mod" module is now only used in these two routines:
    • few internal routines/variables (addPhase, delPhase, new2oldH2O, newHNO3, oldHNO3) are made available through "infotrac" and "infotrac_phy".
    • the "getKey" routine is only used in these two routines to define the explicit keys ("%" operator) of the local derived types "trac_type" and "isot_type". It could be in principle used outside this scope to get tracers parameters (read from "tracer.def") or isotopic parameters (read from "isotopes_params.def" - disabled for now).
  • The fortran parameters file "iso_params_mod.F90" is introduced so that "tnat" and "alpha_ideal" are defined in a single place but used in several. "ltnat1" is no longer hardcoded but defined with the *.def files parameter "tnat1"
  • Few minor changes:
    • use "infotrac_phy" instead of "infotrac" in calfis* because "tracers(:)%isAdvected" is defined in physics only.
    • "isotopes_mod" now ready for several isotopes classes (currently: only H2O)
    • isotopes class name (the name of the parent of the isotopes) is now %name and no longer %parent.
    • improvement of "getKey"
Location:
LMDZ6/trunk/libf/misc
Files:
1 added
1 edited

Legend:

Unmodified
Added
Removed
  • LMDZ6/trunk/libf/misc/readTracFiles_mod.f90

    r5005 r5183  
    1010
    1111  PUBLIC :: maxlen                                              !--- PARAMETER FOR CASUAL STRING LENGTH
    12   PUBLIC :: trac_type, tracers, setGeneration, indexUpdate      !--- TRACERS  DESCRIPTION DATABASE + ASSOCIATED TOOLS
     12  PUBLIC :: keys_type, tracers, setGeneration, indexUpdate      !--- TRACERS  DESCRIPTION DATABASE + ASSOCIATED TOOLS
    1313  PUBLIC :: testTracersFiles, readTracersFiles                  !--- TRACERS FILES READING ROUTINES
    1414  PUBLIC :: getKeysDBase, setKeysDBase                          !--- TOOLS TO GET/SET THE DATABASE (tracers & isotopes)
    1515  PUBLIC :: addTracer, delTracer                                !--- ADD/REMOVE A TRACER FROM
    16   PUBLIC :: addKey,    delKey,    getKey,    keys_type          !--- TOOLS TO SET/DEL/GET KEYS FROM/TO  tracers & isotopes
     16  PUBLIC :: addKey,    delKey,    getKey                        !--- TOOLS TO SET/DEL/GET KEYS FROM/TO  tracers & isotopes
    1717  PUBLIC :: addPhase,  delPhase,  getPhase,  getiPhase,  &      !--- FUNCTIONS RELATED TO THE PHASES
    1818   nphases, old_phases, phases_sep, known_phases, phases_names  !--- + ASSOCIATED VARIABLES
     
    3535  PUBLIC :: itZonIso                                            !--- Idx IN isoName(1:niso) = f(tagging idx, isotope idx)
    3636  PUBLIC :: iqIsoPha                                            !--- Idx IN qx(1:nqtot)     = f(isotope idx,   phase idx)
    37   PUBLIC :: iqWIsoPha                                           !--- Idx IN qx(1:nqtot)     = f(isotope idx,   phase idx) but with normal water first
     37  PUBLIC :: iqWIsoPha                                           !--- SAME AS iqIsoPha BUT ISOTOPES LIST STARTS WITH PARENT TRAC
    3838  PUBLIC :: isoCheck                                            !--- FLAG TO RUN ISOTOPES CHECKING ROUTINES
    3939
     
    4141!------------------------------------------------------------------------------------------------------------------------------
    4242  TYPE :: keys_type                                             !=== TYPE FOR A SET OF KEYS ASSOCIATED TO AN ELEMENT
    43     CHARACTER(LEN=maxlen)              :: name                  !--- Tracer name
    4443    CHARACTER(LEN=maxlen), ALLOCATABLE :: key(:)                !--- Keys string list
    4544    CHARACTER(LEN=maxlen), ALLOCATABLE :: val(:)                !--- Corresponding values string list
    4645  END TYPE keys_type
    4746!------------------------------------------------------------------------------------------------------------------------------
    48   TYPE :: trac_type                                             !=== TYPE FOR A SINGLE TRACER NAMED "name"
    49     CHARACTER(LEN=maxlen) :: name        = ''                   !--- Name of the tracer
    50     TYPE(keys_type)       :: keys                               !--- <key>=<val> pairs vector
    51     CHARACTER(LEN=maxlen) :: gen0Name    = ''                   !--- First generation ancestor name
    52     CHARACTER(LEN=maxlen) :: parent      = ''                   !--- Parent name
    53     CHARACTER(LEN=maxlen) :: longName    = ''                   !--- Long name (with advection scheme suffix)
    54     CHARACTER(LEN=maxlen) :: type        = 'tracer'             !--- Type  (so far: 'tracer' / 'tag')
    55     CHARACTER(LEN=maxlen) :: phase       = 'g'                  !--- Phase ('g'as / 'l'iquid / 's'olid)
    56     CHARACTER(LEN=maxlen) :: component   = ''                   !--- Coma-separated list of components (Ex: lmdz,inca)
    57     INTEGER               :: iGeneration = -1                   !--- Generation number (>=0)
    58     INTEGER               :: iqParent    = 0                    !--- Parent index
    59     INTEGER,  ALLOCATABLE :: iqDescen(:)                        !--- Descendants index (in growing generation order)
    60     INTEGER               :: nqDescen    = 0                    !--- Number of descendants (all generations)
    61     INTEGER               :: nqChildren  = 0                    !--- Number of children  (first generation)
    62     INTEGER               :: iadv        = 10                   !--- Advection scheme used
    63     LOGICAL               :: isAdvected  = .FALSE.              !--- "true" tracers: iadv > 0.   COUNT(isAdvected )=nqtrue
    64     LOGICAL               :: isInPhysics = .TRUE.               !--- "true" tracers: in tr_seri. COUNT(isInPhysics)=nqtottr
    65     INTEGER               :: iso_iGroup  = 0                    !--- Isotopes group index in isotopes(:)
    66     INTEGER               :: iso_iName   = 0                    !--- Isotope  name  index in isotopes(iso_iGroup)%trac(:)
    67     INTEGER               :: iso_iZone   = 0                    !--- Isotope  zone  index in isotopes(iso_iGroup)%zone(:)
    68     INTEGER               :: iso_iPhase  = 0                    !--- Isotope  phase index in isotopes(iso_iGroup)%phase
    69   END TYPE trac_type
    70 !------------------------------------------------------------------------------------------------------------------------------
    71   TYPE :: isot_type                                             !=== TYPE FOR AN ISOTOPES FAMILY DESCENDING ON TRACER "parent"
    72     CHARACTER(LEN=maxlen)              :: parent                !--- Isotopes family name (parent tracer name ; ex: H2O)
     47  TYPE :: isot_type                                             !=== TYPE FOR AN ISOTOPES FAMILY DESCENDING ON TRACER "name"
     48    CHARACTER(LEN=maxlen)              :: name                  !--- Isotopes family name (example: H2O)
    7349    TYPE(keys_type),       ALLOCATABLE :: keys(:)               !--- Isotopes keys/values pairs list     (length: niso)
    7450    LOGICAL                            :: check=.FALSE.         !--- Flag for checking routines triggering
     
    8864  TYPE :: dataBase_type                                         !=== TYPE FOR TRACERS SECTION
    8965    CHARACTER(LEN=maxlen) :: name                               !--- Section name
    90     TYPE(trac_type), ALLOCATABLE :: trac(:)                     !--- Tracers descriptors
     66    TYPE(keys_type), ALLOCATABLE :: trac(:)                     !--- Tracers descriptors
    9167  END TYPE dataBase_type
    9268!------------------------------------------------------------------------------------------------------------------------------
     
    139115
    140116  !=== TRACERS AND ISOTOPES DESCRIPTORS, USED BY getKey
    141   TYPE(trac_type), ALLOCATABLE, TARGET, SAVE ::  tracers(:)
     117  TYPE(keys_type), ALLOCATABLE, TARGET, SAVE ::  tracers(:)
    142118  TYPE(isot_type), ALLOCATABLE, TARGET, SAVE :: isotopes(:)
    143119
     
    193169!------------------------------------------------------------------------------------------------------------------------------
    194170  CHARACTER(LEN=*),                               INTENT(IN)  :: type_trac     !--- List of components used
    195   TYPE(trac_type), ALLOCATABLE, TARGET, OPTIONAL, INTENT(OUT) :: tracs(:)      !--- Tracers descriptor for external storage
     171  TYPE(keys_type), ALLOCATABLE, TARGET, OPTIONAL, INTENT(OUT) :: tracs(:)      !--- Tracers descriptor for external storage
    196172  LOGICAL,                              OPTIONAL, INTENT(IN)  :: lRepr         !--- Activate the HNO3 exceptions for REPROBUS
    197173  CHARACTER(LEN=maxlen),  ALLOCATABLE :: s(:), sections(:), trac_files(:)
    198   CHARACTER(LEN=maxlen) :: str, fname, tname, pname, cname
     174  CHARACTER(LEN=maxlen) :: str, fname, tname, pname, cname, ttype
    199175  INTEGER               :: nsec, ierr, it, ntrac, ns, ip, ix, fType
    200176  INTEGER, ALLOCATABLE  :: iGen(:)
     
    232208        CALL msg('This file is for air tracers only',           modname, ns == 3 .AND. it == 1)
    233209        CALL msg('This files specifies the transporting fluid', modname, ns == 4 .AND. it == 1)
    234         k => tracers(it)%keys
     210        k => tracers(it)
    235211
    236212        !=== NAME OF THE TRACER
     
    238214        ix = strIdx(oldHNO3, s(3))
    239215        IF(ix /= 0 .AND. lRep) tname = newHNO3(ix)                   !--- Exception for HNO3 (REPROBUS ONLY)
    240         tracers(it)%name = tname                                     !--- Set the name of the tracer
    241         CALL addKey('name', tname, k)                                !--- Set the name of the tracer
    242         tracers(it)%keys%name = tname                                !--- Copy tracers names in keys components
     216        CALL addKey('name', tname, tracers)                          !--- Set the name of the tracer
     217!        tracers(it)%name = tname                                     !--- Copy tracers names in keys components
    243218
    244219        !=== NAME OF THE COMPONENT
    245220        cname = type_trac                                            !--- Name of the model component
    246221        IF(ANY([(addPhase('H2O', ip), ip = 1, nphases)] == tname)) cname = 'lmdz'
    247         tracers(it)%component = cname                                !--- Set component
    248         CALL addKey('component', cname, k)                           !--- Set the name of the model component
     222        CALL addKey('component', cname, tracers)                     !--- Set the name of the model component
    249223
    250224        !=== NAME OF THE PARENT
     
    255229          IF(ix /= 0 .AND. lRep) pname = newHNO3(ix)                 !--- Exception for HNO3 (REPROBUS ONLY)
    256230        END IF
    257         tracers(it)%parent = pname                                   !--- Set the parent name
    258         CALL addKey('parent', pname, k)
     231        CALL addKey('parent', pname, tracers)                        !--- Set the parent name
    259232
    260233        !=== PHASE AND ADVECTION SCHEMES NUMBERS
    261         tracers(it)%phase = known_phases(ip:ip)                      !--- Set the phase of the tracer (default: "g"azeous)
    262         CALL addKey('phase', known_phases(ip:ip), k)                 !--- Set the phase of the tracer (default: "g"azeous)
     234        CALL addKey('phase', known_phases(ip:ip), tracers)           !--- Set the phase of the tracer (default: "g"azeous)
    263235        CALL addKey('hadv', s(1),  k)                                !--- Set the horizontal advection schemes number
    264236        CALL addKey('vadv', s(2),  k)                                !--- Set the vertical   advection schemes number
     
    266238      CLOSE(90)
    267239      lerr = setGeneration(tracers); IF(lerr) RETURN                 !--- Set iGeneration and gen0Name
    268       lerr = getKey('iGeneration', iGen, tracers(:)%keys)            !--- Generation number
    269       WHERE(iGen == 2) tracers(:)%type = 'tag'                       !--- Set type:      'tracer' or 'tag'
     240      lerr = getKey('iGeneration', iGen, tracers(:))                 !--- Generation number
    270241      DO it = 1, ntrac
    271         CALL addKey('type', tracers(it)%type, tracers(it)%keys)      !--- Set the type of tracer
     242        ttype = 'tracer'; IF(iGen(it) == 2) ttype = 'tag'
     243        CALL addKey('type', ttype, tracers(it))                 !--- Set the type of tracer
    272244      END DO
    273245      lerr = checkTracers(tracers, fname, fname); IF(lerr) RETURN    !--- Detect orphans and check phases
     
    291263  END IF
    292264  lerr = indexUpdate(tracers); IF(lerr) RETURN                       !--- Set iqParent, iqDescen, nqDescen, nqChildren
    293   IF(PRESENT(tracs)) CALL MOVE_ALLOC(FROM=tracers, TO=tracs)
     265  IF(PRESENT(tracs)) tracs = tracers
    294266END FUNCTION readTracersFiles
    295267!==============================================================================================================================
     
    339311! Purpose: Read the sections "snames(is)" (pipe-separated list) from each "fnames(is)"
    340312!   file and create the corresponding tracers set descriptors in the database "dBase":
    341 ! * dBase(id)%name                : section name
    342 ! * dBase(id)%trac(:)%name        : tracers names
    343 ! * dBase(id)%trac(it)%keys%key(:): names  of keys associated to tracer dBase(id)%trac(it)%name
    344 ! * dBase(id)%trac(it)%keys%val(:): values of keys associated to tracer dBase(id)%trac(it)%name
     313! * dBase(id)%name           : section name
     314! * dBase(id)%trac(:)        : tracers descriptor (the key "name" of tracers(i) is the name of the ith tracer)
     315! * dBase(id)%trac(it)%key(:): names  of keys associated to tracer dBase(id)%trac(it)%name
     316! * dBase(id)%trac(it)%val(:): values of keys associated to tracer dBase(id)%trac(it)%name
    345317!------------------------------------------------------------------------------------------------------------------------------
    346318  CHARACTER(LEN=*), INTENT(IN)  :: fnames(:)                         !--- Files names
     
    395367  ndb= SIZE(dBase)                                                   !--- Current number of sections in the database
    396368  IF(PRESENT(defName)) THEN                                          !--- Add default values to all the tracers
    397     DO idb=n0,ndb; CALL addDefault(dBase(idb)%trac, defName); END DO !--- and remove the virtual tracer "defName"
     369    DO idb=n0,ndb                                                    !--- and remove the virtual tracer "defName"
     370       lerr = addDefault(dBase(idb)%trac, defName); IF(lerr) RETURN
     371    END DO
    398372  END IF
    399373  ll = strParse(snam, '|', keys = sec)                               !--- Requested sections names
     
    408382!------------------------------------------------------------------------------------------------------------------------------
    409383  CHARACTER(LEN=maxlen), ALLOCATABLE ::  s(:), v(:)
    410   TYPE(trac_type),       ALLOCATABLE :: tt(:)
    411   TYPE(trac_type)       :: tmp
     384  TYPE(keys_type),       ALLOCATABLE :: tt(:)
    412385  CHARACTER(LEN=1024)   :: str, str2
    413386  CHARACTER(LEN=maxlen) :: secn
     
    445418      tt = dBase(ndb)%trac(:)
    446419      v(1) = s(1); s(1) = 'name'                                     !--- Convert "name" into a regular key
    447       tmp%name = v(1); tmp%keys = keys_type(v(1), s(:), v(:))        !--- Set %name and %keys
    448       dBase(ndb)%trac = [tt(:), tmp]
    449       DEALLOCATE(tt, tmp%keys%key, tmp%keys%val)
     420      dBase(ndb)%trac = [tt(:), keys_type(s(:), v(:))]
     421      DEALLOCATE(tt)
    450422    END IF
    451423  END DO
     
    460432
    461433!==============================================================================================================================
    462 SUBROUTINE addDefault(t, defName)
     434LOGICAL FUNCTION addDefault(t, defName) RESULT(lerr)
    463435!------------------------------------------------------------------------------------------------------------------------------
    464436! Purpose: Add the keys from virtual tracer named "defName" (if any) and remove this virtual tracer.
    465437!------------------------------------------------------------------------------------------------------------------------------
    466   TYPE(trac_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: t(:)
     438  TYPE(keys_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: t(:)
    467439  CHARACTER(LEN=*),                     INTENT(IN)    :: defName
    468440  INTEGER :: jd, it, k
    469   TYPE(keys_type), POINTER :: ky
    470   TYPE(trac_type), ALLOCATABLE :: tt(:)
    471   jd = strIdx(t(:)%name, defName)
     441  CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:)
     442  TYPE(keys_type),       ALLOCATABLE :: tt(:)
     443  lerr = getKey('name', tname, t(:)); IF(lerr) RETURN
     444  jd = strIdx(tname(:), defName)
    472445  IF(jd == 0) RETURN
    473   ky => t(jd)%keys
    474   DO k = 1, SIZE(ky%key)                                             !--- Loop on the keys of the tracer named "defName"
    475 !   CALL addKey(ky%key(k), ky%val(k), t(:)%keys, .FALSE.)            !--- Add key to all the tracers (no overwriting)
    476     DO it = 1, SIZE(t); CALL addKey(ky%key(k), ky%val(k), t(it)%keys, .FALSE.); END DO
     446  DO k = 1, SIZE(t(jd)%key)                                          !--- Loop on the keys of the tracer named "defName"
     447!   CALL addKey(t(jd)%key(k), t(jd)%val(k), t(:), .FALSE.)           !--- Add key to all the tracers (no overwriting)
     448    DO it = 1, SIZE(t); CALL addKey(t(jd)%key(k), t(jd)%val(k), t(it), .FALSE.); END DO
    477449  END DO
    478450  tt = [t(1:jd-1),t(jd+1:SIZE(t))]; CALL MOVE_ALLOC(FROM=tt, TO=t)   !--- Remove the virtual tracer named "defName"
    479 END SUBROUTINE addDefault
    480 !==============================================================================================================================
    481 
    482 !==============================================================================================================================
    483 SUBROUTINE subDefault(t, defName, lSubLocal)
     451END FUNCTION addDefault
     452!==============================================================================================================================
     453
     454!==============================================================================================================================
     455LOGICAL FUNCTION subDefault(t, defName, lSubLocal) RESULT(lerr)
    484456!------------------------------------------------------------------------------------------------------------------------------
    485457! Purpose: Substitute the keys from virtual tracer named "defName" (if any) and remove this virtual tracer.
    486458!          Substitute the keys locally (for the current tracer) if the flag "lSubLocal" is .TRUE.
    487459!------------------------------------------------------------------------------------------------------------------------------
    488   TYPE(trac_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: t(:)
     460  TYPE(keys_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: t(:)
    489461  CHARACTER(LEN=*),                     INTENT(IN)    :: defName
    490462  LOGICAL,                              INTENT(IN)    :: lSubLocal
    491463  INTEGER :: i0, it, ik
    492   TYPE(keys_type), POINTER     :: k0, ky
    493   TYPE(trac_type), ALLOCATABLE :: tt(:)
    494   i0 = strIdx(t(:)%name, defName)
     464  TYPE(keys_type),       ALLOCATABLE :: tt(:)
     465  CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:)
     466  lerr = getKey('name', tname, t(:)); IF(lerr) RETURN
     467  i0 = strIdx(tname(:), defName)
    495468  IF(i0 == 0) RETURN
    496   k0 => t(i0)%keys
    497469  DO it = 1, SIZE(t); IF(it == i0) CYCLE                             !--- Loop on the tracers
    498     ky => t(it)%keys
    499470
    500471    !--- Substitute in the values of <key>=<val> pairs the keys defined in the virtual tracer "defName"
    501     DO ik = 1, SIZE(k0%key); CALL strReplace(ky%val, k0%key(ik), k0%val(ik), .TRUE.); END DO
     472    DO ik = 1, SIZE(t(i0)%key); CALL strReplace(t(it)%val, t(i0)%key(ik), t(i0)%val(ik), .TRUE.); END DO
    502473
    503474    IF(.NOT.lSubLocal) CYCLE
    504475    !--- Substitute in the values of <key>=<val> pairs the keys defined locally (in the current tracer)
    505     DO ik = 1, SIZE(ky%key); CALL strReplace(ky%val, ky%key(ik), ky%val(ik), .TRUE.); END DO
     476    DO ik = 1, SIZE(t(it)%key); CALL strReplace(t(it)%val, t(it)%key(ik), t(it)%val(ik), .TRUE.); END DO
    506477  END DO
    507478  tt = [t(1:i0-1),t(i0+1:SIZE(t))]; CALL MOVE_ALLOC(FROM=tt, TO=t)   !--- Remove the virtual tracer named "defName"
    508479
    509 END SUBROUTINE subDefault
     480END FUNCTION subDefault
    510481!==============================================================================================================================
    511482
     
    518489!        * Default values are provided for these keys because they are necessary.
    519490!------------------------------------------------------------------------------------------------------------------------------
    520   TYPE(trac_type), ALLOCATABLE, INTENT(INOUT) :: tr(:)                 !--- Tracer derived type vector
     491  TYPE(keys_type), ALLOCATABLE, INTENT(INOUT) :: tr(:)                 !--- Tracer derived type vector
    521492  CHARACTER(LEN=*),             INTENT(IN)    :: sname                 !--- Current section name
    522493  CHARACTER(LEN=*), OPTIONAL,   INTENT(IN)    :: fname                 !--- Tracers description file name
    523   TYPE(trac_type),       ALLOCATABLE :: ttr(:)
     494  TYPE(keys_type),       ALLOCATABLE :: ttr(:)
    524495  CHARACTER(LEN=maxlen), ALLOCATABLE :: ta(:), pa(:), tname(:), parent(:), dType(:)
    525496  CHARACTER(LEN=maxlen) :: msg1, modname
     
    529500  lerr = .FALSE.
    530501  nt = SIZE(tr)
    531   lerr = getKey('name',   tname,  tr(:)%keys);                 IF(lerr) RETURN
    532   lerr = getKey('parent', parent, tr(:)%keys, def = tran0);    IF(lerr) RETURN
    533   lerr = getKey('type',   dType,  tr(:)%keys, def = 'tracer'); IF(lerr) RETURN
     502  lerr = getKey('name',   tname,  tr(:));                 IF(lerr) RETURN
     503  lerr = getKey('parent', parent, tr(:), def = tran0);    IF(lerr) RETURN
     504  lerr = getKey('type',   dType,  tr(:), def = 'tracer'); IF(lerr) RETURN
    534505  nq = 0
    535506  !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     
    537508  !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    538509    !--- Extract useful keys: parent name, type, component name
    539     tr(it)%component = sname
    540     CALL addKey('component', sname,  tr(it)%keys)
     510    CALL addKey('component', sname,  tr(it))
    541511
    542512    !--- Determine the number of tracers and parents ; coherence checking
     
    565535    DO ipr = 1, npr                                                  !--- Loop on parents list elts
    566536      DO itr = 1, ntr                                                !--- Loop on tracers list elts
    567         ttr(iq)%keys%name = TRIM(ta(itr))
    568         ttr(iq)%keys%key  = tr(it)%keys%key
    569         ttr(iq)%keys%val  = tr(it)%keys%val
    570         ttr(iq)%name      = TRIM(ta(itr))
    571         ttr(iq)%parent    = TRIM(pa(ipr))
    572         ttr(iq)%type      = dType(it)
    573         ttr(iq)%component = sname
    574         CALL addKey('name',      ta(itr),   ttr(iq)%keys)
    575         CALL addKey('parent',    pa(ipr),   ttr(iq)%keys)
    576         CALL addKey('type',      dType(it), ttr(iq)%keys)
    577         CALL addKey('component', sname,     ttr(iq)%keys)
     537        ttr(iq)%key  = tr(it)%key
     538        ttr(iq)%val  = tr(it)%val
     539        CALL addKey('name',    ta(itr), ttr(iq))
     540        CALL addKey('parent',  pa(ipr), ttr(iq))
     541        CALL addKey('type',  dType(it), ttr(iq))
     542        CALL addKey('component', sname, ttr(iq))
    578543        iq = iq + 1
    579544      END DO
     
    597562!          Check also for orphan tracers (tracers without parent).
    598563!------------------------------------------------------------------------------------------------------------------------------
    599   TYPE(trac_type),     INTENT(INOUT) :: tr(:)                        !--- Tracer derived type vector
     564  TYPE(keys_type),     INTENT(INOUT) :: tr(:)                        !--- Tracer derived type vector
    600565  INTEGER                            :: iq, jq, ig
    601566  CHARACTER(LEN=maxlen), ALLOCATABLE :: parent(:), tname(:)
     
    603568  CHARACTER(LEN=maxlen) :: modname
    604569  modname = 'setGeneration'
    605   lerr = getKey('name',   tname,  ky=tr(:)%keys); IF(lerr) RETURN
    606   lerr = getKey('parent', parent, ky=tr(:)%keys); IF(lerr) RETURN
     570  lerr = getKey('name',   tname,  ky=tr(:)); IF(lerr) RETURN
     571  lerr = getKey('parent', parent, ky=tr(:)); IF(lerr) RETURN
    607572  DO iq = 1, SIZE(tr)
    608573    jq = iq; ig = 0
     
    613578      ig = ig + 1
    614579    END DO
    615     tr(iq)%gen0Name = tname(jq)
    616     tr(iq)%iGeneration = ig
    617     CALL addKey('iGeneration',   ig,  tr(iq)%keys)
    618     CALL addKey('gen0Name', tname(jq), tr(iq)%keys)
     580    CALL addKey('iGeneration',    ig,  tr(iq))
     581    CALL addKey('gen0Name', tname(jq), tr(iq))
    619582  END DO
    620583END FUNCTION setGeneration
     
    629592!   * check wether the phases are known or not (elements of "known_phases")
    630593!------------------------------------------------------------------------------------------------------------------------------
    631   TYPE(trac_type),            INTENT(IN) :: tr(:)                    !--- Tracer derived type vector
     594  TYPE(keys_type),            INTENT(IN) :: tr(:)                    !--- Tracers description vector
    632595  CHARACTER(LEN=*),           INTENT(IN) :: sname                    !--- Section name
    633596  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: fname                    !--- File name
     
    644607  mesg = 'Check section "'//TRIM(sname)//'"'
    645608  IF(PRESENT(fname)) mesg=TRIM(mesg)//' in file "'//TRIM(fname)//'"'
    646   lerr = getKey('iGeneration', iGen, tr(:)%keys);               IF(lerr) RETURN
    647   lerr = getKey('name',       tname, tr(:)%keys);               IF(lerr) RETURN
     609  lerr = getKey('iGeneration', iGen, tr(:));                    IF(lerr) RETURN
     610  lerr = getKey('name',       tname, tr(:));                    IF(lerr) RETURN
    648611
    649612  !=== CHECK FOR ORPHAN TRACERS
     
    652615  !=== CHECK PHASES
    653616  DO iq = 1, nq; IF(iGen(iq) /= 0) CYCLE                             !--- Generation O only is checked
    654     IF(getKey(['phases','phase '], pha, iq, tr(:)%keys, lDisp=.FALSE.)) pha = 'g'   !--- Phase
     617    IF(getKey(['phases','phase '], pha, iq, tr(:), lDisp=.FALSE.)) pha = 'g'   !--- Phase
    655618    np = LEN_TRIM(pha); bp(iq)=' '
    656619    DO ip = 1, np; p = pha(ip:ip); IF(INDEX(known_phases, p) == 0) bp(iq) = TRIM(bp(iq))//p; END DO
     
    667630! Purpose: Make sure that tracers are not repeated.
    668631!------------------------------------------------------------------------------------------------------------------------------
    669   TYPE(trac_type),            INTENT(IN) :: tr(:)                    !--- Tracer derived type vector
     632  TYPE(keys_type),            INTENT(IN) :: tr(:)                    !--- Tracers description vector
    670633  CHARACTER(LEN=*),           INTENT(IN) :: sname                    !--- Section name
    671634  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: fname                    !--- File name
     
    684647  nq=SIZE(tr,DIM=1); lerr=.FALSE.                                    !--- Number of lines ; error flag
    685648  tdup(:) = ''
    686   lerr = getKey('name',       tname, tr%keys); IF(lerr) RETURN
    687   lerr = getKey('type',       dType, tr%keys); IF(lerr) RETURN
    688   lerr = getKey('iGeneration', iGen, tr%keys); IF(lerr) RETURN
     649  lerr = getKey('name',       tname, tr); IF(lerr) RETURN
     650  lerr = getKey('type',       dType, tr); IF(lerr) RETURN
     651  lerr = getKey('iGeneration', iGen, tr); IF(lerr) RETURN
    689652  DO iq = 1, nq
    690653    IF(dType(iq) == 'tag') CYCLE                                     !--- Tags can be repeated
     
    698661        DO k = 1, nq
    699662          IF(.NOT.ll(k)) CYCLE                                       !--- Skip tracers different from current one
    700           IF(getKey(['phases','phase '], phase, k, tr%keys, lDisp=.FALSE.)) phase='g'!--- Get current phases
     663          IF(getKey(['phases','phase '], phase, k, tr, lDisp=.FALSE.)) phase='g'!--- Get current phases
    701664          IF(INDEX(phase, p) /= 0) np = np + 1                       !--- One more appearance of current tracer with phase "p"
    702665        END DO
     
    718681! Purpose: Expand the phases in the tracers descriptor "tr". Phases are not repeated for a tracer, thanks to "checkUnique".
    719682!------------------------------------------------------------------------------------------------------------------------------
    720   TYPE(trac_type), ALLOCATABLE, INTENT(INOUT) :: tr(:)               !--- Tracer derived type vector
    721 !------------------------------------------------------------------------------------------------------------------------------
    722   TYPE(trac_type),       ALLOCATABLE :: ttr(:)
     683  TYPE(keys_type), ALLOCATABLE, INTENT(INOUT) :: tr(:)               !--- Tracers description vector
     684!------------------------------------------------------------------------------------------------------------------------------
     685  TYPE(keys_type),       ALLOCATABLE :: ttr(:)
    723686  INTEGER,               ALLOCATABLE ::  i0(:), iGen(:)
    724687  CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:), gen0N(:), phase(:), parents(:), dType(:)
     
    732695  nq = SIZE(tr, DIM=1)
    733696  nt = 0
    734   lerr = getKey('name',       tname, tr%keys); IF(lerr) RETURN       !--- Names of the tracers
    735   lerr = getKey('gen0Name',   gen0N, tr%keys); IF(lerr) RETURN       !--- Names of the tracers of first generation
    736   lerr = getKey('iGeneration', iGen, tr%keys); IF(lerr) RETURN       !--- Generation number
    737   lerr = getKey('phases',     phase, tr%keys); IF(lerr) RETURN       !--- Phases names
    738   lerr = getKey('parent',   parents, tr%keys); IF(lerr) RETURN       !--- Parents names
    739   lerr = getKey('type',       dType, tr%keys); IF(lerr) RETURN       !--- Tracers types ('tracer' or 'tag')
     697  lerr = getKey('name',       tname, tr); IF(lerr) RETURN            !--- Names of the tracers
     698  lerr = getKey('gen0Name',   gen0N, tr); IF(lerr) RETURN            !--- Names of the tracers of first generation
     699  lerr = getKey('iGeneration', iGen, tr); IF(lerr) RETURN            !--- Generation number
     700  lerr = getKey('phases',     phase, tr); IF(lerr) RETURN            !--- Phases names
     701  lerr = getKey('parent',   parents, tr); IF(lerr) RETURN            !--- Parents names
     702  lerr = getKey('type',       dType, tr); IF(lerr) RETURN            !--- Tracers types ('tracer' or 'tag')
    740703  DO iq = 1, nq                                                      !--- GET THE NUMBER OF TRACERS
    741704    IF(iGen(iq) /= 0) CYCLE                                          !--- Only deal with generation 0 tracers
     
    763726        IF(lTag) nam = TRIM(nam)//'_'//TRIM(tname(iq))               !--- <parent>_<name> for tags
    764727        ttr(it) = tr(iq)                                             !--- Same <key>=<val> pairs
    765         ttr(it)%name      = TRIM(nam)                                !--- Name with possibly phase suffix
    766         ttr(it)%keys%name = TRIM(nam)                                !--- Name inside the keys decriptor
    767         ttr(it)%phase     = p                                        !--- Single phase entry
    768         CALL addKey('name', nam, ttr(it)%keys)
    769         CALL addKey('phase', p,  ttr(it)%keys)
     728        CALL addKey('name', nam, ttr(it))                            !--- Name with possibly phase suffix
     729        CALL addKey('phase', p,  ttr(it))                            !--- Single phase entry
    770730        IF(lExt) THEN
    771731          parent = parents(iq); IF(iGen(iq) > 0) parent = addPhase(parent, p)
    772732          gen0Nm =   gen0N(iq); IF(iGen(iq) > 0) gen0Nm = addPhase(gen0Nm, p)
    773           ttr(it)%parent   = parent
    774           ttr(it)%gen0Name = gen0Nm
    775           CALL addKey('parent',   parent, ttr(it)%keys)
    776           CALL addKey('gen0Name', gen0Nm, ttr(it)%keys)
     733          CALL addKey('parent',   parent, ttr(it))
     734          CALL addKey('gen0Name', gen0Nm, ttr(it))
    777735        END IF
    778736        it = it+1
     
    782740  END DO
    783741  CALL MOVE_ALLOC(FROM=ttr, TO=tr)
    784   CALL delKey(['phases'],tr)                                         !--- Remove few keys entries
     742  CALL delKey(['phases'], tr)                                        !--- Remove "phases" key, useless since "phase" is defined
    785743
    786744END FUNCTION expandPhases
     
    797755!   TO BE ADDED IF NECESSARY: HIGHER MOMENTS AT THE END
    798756!------------------------------------------------------------------------------------------------------------------------------
    799   TYPE(trac_type), INTENT(INOUT) :: tr(:)                            !--- Tracer derived type vector
    800 !------------------------------------------------------------------------------------------------------------------------------
    801   TYPE(trac_type),       ALLOCATABLE :: tr2(:)
    802   INTEGER,               ALLOCATABLE :: iy(:), iz(:)
    803   INTEGER,               ALLOCATABLE ::  iGen(:)
     757  TYPE(keys_type), INTENT(INOUT) :: tr(:)                            !--- Tracers description vector
     758!------------------------------------------------------------------------------------------------------------------------------
     759  TYPE(keys_type),       ALLOCATABLE :: tr2(:)
     760  INTEGER,               ALLOCATABLE :: iy(:), iz(:), iGen(:)
    804761  CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:), gen0N(:)
    805762  INTEGER :: ig, ng, iq, jq, ip, nq, n, ix(SIZE(tr)), k
     
    807764!  tr2 is introduced in order to cope with a bug in gfortran 4.8.5 compiler
    808765!------------------------------------------------------------------------------------------------------------------------------
    809   lerr = getKey('iGeneration', iGen, tr%keys); IF(lerr) RETURN       !--- Generation number
     766  lerr = getKey('iGeneration', iGen, tr); IF(lerr) RETURN            !--- Generation number
    810767  nq = SIZE(tr)
    811768  DO ip = nphases, 1, -1
    812     lerr = getKey('name',     tname, tr%keys); IF(lerr) RETURN       !--- Names of the tracers of first generation
     769    lerr = getKey('name',     tname, tr); IF(lerr) RETURN            !--- Names of the tracers of first generation
    813770    iq = strIdx(tname, addPhase('H2O', ip))
    814771    IF(iq == 0) CYCLE
     
    826783    END DO
    827784  ELSE
    828     lerr = getKey('gen0Name',   gen0N, tr%keys); IF(lerr) RETURN     !--- Names of the tracers    iq = 1
     785    lerr = getKey('gen0Name', gen0N, tr); IF(lerr) RETURN            !--- Names of the tracers    iq = 1
    829786    DO jq = 1, nq                                                    !--- Loop on generation 0 tracers
    830787      IF(iGen(jq) /= 0) CYCLE                                        !--- Skip generations /= 0
     
    848805LOGICAL FUNCTION mergeTracers(sections, tr) RESULT(lerr)
    849806  TYPE(dataBase_type),  TARGET, INTENT(IN)  :: sections(:)
    850   TYPE(trac_type), ALLOCATABLE, INTENT(OUT) ::       tr(:)
    851   TYPE(trac_type), POINTER ::   t1(:),   t2(:)
    852   TYPE(keys_type), POINTER ::   k1(:),   k2(:)
     807  TYPE(keys_type), ALLOCATABLE, INTENT(OUT) ::       tr(:)
     808  TYPE(keys_type), POINTER ::   t1(:),   t2(:)
    853809  INTEGER,     ALLOCATABLE :: ixct(:), ixck(:)
    854810  INTEGER :: is, ik, ik1, ik2, nk2, i1, i2, nt2
     
    858814  lerr = .FALSE.
    859815  keys = ['parent     ', 'type       ', 'iGeneration']               !--- Mandatory keys
    860   t1 => sections(1)%trac(:); k1 => t1(:)%keys                        !--- Alias: first tracers section, corresponding keys
    861   lerr = getKey('name', n1, k1); IF(lerr) RETURN                     !--- Names of the tracers
     816  t1 => sections(1)%trac(:)                                          !--- Alias: first tracers section
     817  lerr = getKey('name', n1, t1); IF(lerr) RETURN                     !--- Names of the tracers
    862818  tr = t1
    863819  !----------------------------------------------------------------------------------------------------------------------------
     
    865821  !----------------------------------------------------------------------------------------------------------------------------
    866822    t2  => sections(is)%trac(:)                                      !--- Alias: current tracers section
    867     k2  => t2(:)%keys
    868     lerr = getKey('name', n2, k2); IF(lerr) RETURN                   !--- Names of the tracers
     823    lerr = getKey('name', n2, t2); IF(lerr) RETURN                   !--- Names of the tracers
    869824    nt2  = SIZE(t2(:), DIM=1)                                        !--- Number of tracers in section
    870825    ixct = strIdx(n1(:), n2(:))                                      !--- Indexes of common tracers
     
    874829    CALL msg(n1(PACK(ixct, MASK = ixct/=0)), modname, nmax=128)      !--- Display duplicates (the 128 first at most)
    875830    !--------------------------------------------------------------------------------------------------------------------------
    876     DO i2=1,nt2; tnam = TRIM(t2(i2)%name)                            !=== LOOP ON COMMON TRACERS
     831    DO i2=1,nt2; tnam = TRIM(n2(i2))                                 !=== LOOP ON COMMON TRACERS
    877832    !--------------------------------------------------------------------------------------------------------------------------
    878833      i1 = ixct(i2); IF(i1 == 0) CYCLE                               !--- Idx in t1(:) ; skip new tracers
     
    881836      s1=' of "'//TRIM(tnam)//'" in "'//TRIM(sections(is)%name)//'" not matching previous value'
    882837      DO ik = 1, SIZE(keys)
    883         lerr = getKey(keys(ik), v1, i1, k1)
    884         lerr = getKey(keys(ik), v2, i2, k2)
     838        lerr = getKey(keys(ik), v1, i1, t1)
     839        lerr = getKey(keys(ik), v2, i2, t2)
    885840        lerr = v1 /= v2; IF(fmsg(TRIM(keys(ik))//TRIM(s1), modname, lerr)) RETURN
    886841      END DO
    887842
    888       !=== GET THE INDICES IN tr(i2)%keys%key(:) OF THE KEYS ALSO PRESENT IN tr(i1)%keys%key(:)
    889       nk2  =   SIZE(k2(i2)%key(:))                                   !--- Keys number in current section
    890       ixck = strIdx(k1(i1)%key(:), k2(i2)%key(:))                    !--- Common keys indexes
    891       !--- APPEND THE NEW KEYS PAIRS IN tr(i1)%keys%key(:)
    892       tr(i1)%keys%key = [ tr(i1)%keys%key, PACK(tr(i2)%keys%key, MASK = ixck==0)]
    893       tr(i1)%keys%val = [ tr(i1)%keys%val, PACK(tr(i2)%keys%val, MASK = ixck==0)]
     843      !=== GET THE INDICES IN tr(i2)%key(:) OF THE KEYS ALSO PRESENT IN tr(i1)%key(:)
     844      nk2  =   SIZE(t2(i2)%key(:))                                   !--- Keys number in current section
     845      ixck = strIdx(t1(i1)%key(:), t2(i2)%key(:))                    !--- Common keys indexes
     846      !--- APPEND THE NEW KEYS PAIRS IN tr(i1)%key(:)
     847      tr(i1)%key = [ tr(i1)%key, PACK(tr(i2)%key, MASK = ixck==0)]
     848      tr(i1)%val = [ tr(i1)%val, PACK(tr(i2)%val, MASK = ixck==0)]
    894849
    895850      !=== KEEP TRACK OF THE COMPONENTS NAMES: COMA-SEPARATED LIST
    896       lerr = getKey('component', v1, i1, k1)
    897       lerr = getKey('component', v2, i2, k2)
    898       tr(i1)%component = TRIM(v1)//','//TRIM(v2)
    899       CALL addKey('component', TRIM(v1)//','//TRIM(v2), tr(i1)%keys)
     851      lerr = getKey('component', v1, i1, t1)
     852      lerr = getKey('component', v2, i2, t2)
     853      CALL addKey('component', TRIM(v1)//','//TRIM(v2), tr(i1))
    900854
    901855      !=== FOR TRACERS COMMON TO PREVIOUS AND CURRENT SECTIONS: CHECK WETHER SOME KEYS HAVE DIFFERENT VALUES ; KEEP OLD ONE
    902856      DO ik2 = 1, nk2                                                !--- Collect the corresponding indices
    903857        ik1 = ixck(ik2); IF(ik1 == 0) CYCLE
    904         IF(k1(i1)%val(ik1) == k2(i2)%val(ik2)) ixck(ik2)=0
     858        IF(t1(i1)%val(ik1) == t2(i2)%val(ik2)) ixck(ik2)=0
    905859      END DO
    906860      IF(ALL(ixck==0)) CYCLE                                         !--- No identical keys with /=values => nothing to display
    907861      CALL msg('Key(s)'//TRIM(s1), modname)                          !--- Display the  keys with /=values (names list)
    908862      DO ik2 = 1, nk2                                                !--- Loop on keys found in both t1(:) and t2(:)
    909         knam = k2(i2)%key(ik2)                                       !--- Name of the current key
     863        knam = t2(i2)%key(ik2)                                       !--- Name of the current key
    910864        ik1 = ixck(ik2)                                              !--- Corresponding index in t1(:)
    911865        IF(ik1 == 0) CYCLE                                           !--- New keys are skipped
    912         v1 = k1(i1)%val(ik1); v2 = k2(i2)%val(ik2)                   !--- Key values in t1(:) and t2(:)
     866        v1 = t1(i1)%val(ik1); v2 = t2(i2)%val(ik2)                   !--- Key values in t1(:) and t2(:)
    913867        CALL msg(' * '//TRIM(knam)//'='//TRIM(v2)//' ; previous value kept:'//TRIM(v1), modname)
    914868      END DO
     
    925879LOGICAL FUNCTION cumulTracers(sections, tr, lRename) RESULT(lerr)
    926880  TYPE(dataBase_type),  TARGET, INTENT(IN)  :: sections(:)
    927   TYPE(trac_type), ALLOCATABLE, INTENT(OUT) ::       tr(:)
     881  TYPE(keys_type), ALLOCATABLE, INTENT(OUT) ::       tr(:)
    928882  LOGICAL,            OPTIONAL, INTENT(IN)  :: lRename               !--- .TRUE.: add a section suffix to identical names
    929883  CHARACTER(LEN=maxlen)  :: tnam_new, modname
     
    934888  tr = [( sections(is)%trac(:), is = 1, SIZE(sections) )]            !--- Concatenated tracers vector
    935889  IF(PRESENT(lRename)) THEN; IF(lRename) RETURN; END IF              !--- No renaming: finished
    936   lerr = getKey('name',     tname, tr%keys); IF(lerr) RETURN         !--- Names
    937   lerr = getKey('parent',  parent, tr%keys); IF(lerr) RETURN         !--- Parents
    938   lerr = getKey('component', comp, tr%keys); IF(lerr) RETURN         !--- Component name
     890  lerr = getKey('name',     tname, tr); IF(lerr) RETURN              !--- Names
     891  lerr = getKey('parent',  parent, tr); IF(lerr) RETURN              !--- Parents
     892  lerr = getKey('component', comp, tr); IF(lerr) RETURN              !--- Component name
    939893  !----------------------------------------------------------------------------------------------------------------------------
    940894  DO iq = 1, SIZE(tr); IF(COUNT(tname == tname(iq)) == 1) CYCLE      !=== LOOP ON TRACERS
    941895  !----------------------------------------------------------------------------------------------------------------------------
    942896    tnam_new = TRIM(tname(iq))//'_'//TRIM(comp(iq))                  !--- Same with section extension
    943     CALL addKey('name', tnam_new, tr(iq)%keys)                       !--- Modify tracer name
    944     tr(iq)%name = TRIM(tnam_new)                                     !--- Modify tracer name
     897    CALL addKey('name', tnam_new, tr(iq))                            !--- Modify tracer name
    945898    !--------------------------------------------------------------------------------------------------------------------------
    946899    DO jq = 1, SIZE(tr); IF(parent(jq) /= tname(iq)) CYCLE           !=== LOOP ON TRACERS PARENTS
    947900    !--------------------------------------------------------------------------------------------------------------------------
    948       CALL addKey('parent', tnam_new, tr(jq)%keys)                   !--- Modify tracer name
    949       tr(jq)%parent = TRIM(tnam_new)                                 !--- Modify tracer name
     901      CALL addKey('parent', tnam_new, tr(jq))                        !--- Modify tracer name
    950902    !--------------------------------------------------------------------------------------------------------------------------
    951903    END DO
     
    994946    tmp = int2str([(iq, iq=1, nq)])
    995947  ELSE
    996     lerr = getKey(nam, tmp, dBase(idb)%trac(:)%keys, lDisp=lMandatory)
     948    lerr = getKey(nam, tmp, dBase(idb)%trac(:), lDisp=lMandatory)
    997949  END IF
    998950  IF(lerr) THEN; lerr = lMandatory; RETURN; END IF
     
    1013965LOGICAL FUNCTION aliasTracer(tname, trac, alias) RESULT(lerr)                  !=== TRACER NAMED "tname" - SCALAR
    1014966  CHARACTER(LEN=*),         INTENT(IN)  :: tname
    1015   TYPE(trac_type), TARGET,  INTENT(IN)  :: trac(:)
    1016   TYPE(trac_type), POINTER, INTENT(OUT) :: alias
     967  TYPE(keys_type), TARGET,  INTENT(IN)  :: trac(:)
     968  TYPE(keys_type), POINTER, INTENT(OUT) :: alias
    1017969  INTEGER :: it
    1018970  CHARACTER(LEN=maxlen), ALLOCATABLE :: tnames(:)
    1019971  alias => NULL()
    1020   lerr = getKey('name', tnames, trac(:)%keys)
     972  lerr = getKey('name', tnames, trac(:))
    1021973  it = strIdx(tnames, tname)
    1022974  lerr = it /= 0; IF(.NOT.lerr) alias => trac(it)
     
    1024976!==============================================================================================================================
    1025977LOGICAL FUNCTION trSubset_Indx(trac, idx, alias) RESULT(lerr)                  !=== TRACERS WITH INDICES "idx(:)" - VECTOR
    1026   TYPE(trac_type), ALLOCATABLE, INTENT(IN)  ::  trac(:)
     978  TYPE(keys_type), ALLOCATABLE, INTENT(IN)  ::  trac(:)
    1027979  INTEGER,                      INTENT(IN)  ::   idx(:)
    1028   TYPE(trac_type), ALLOCATABLE, INTENT(OUT) :: alias(:)
     980  TYPE(keys_type), ALLOCATABLE, INTENT(OUT) :: alias(:)
    1029981  alias = trac(idx)
    1030982  lerr = indexUpdate(alias)
     
    1032984!------------------------------------------------------------------------------------------------------------------------------
    1033985LOGICAL FUNCTION trSubset_Name(trac, tname, alias) RESULT(lerr)                !=== TRACERS NAMED "tname(:)" - VECTOR
    1034   TYPE(trac_type), ALLOCATABLE, INTENT(IN)  ::  trac(:)
     986  TYPE(keys_type), ALLOCATABLE, INTENT(IN)  ::  trac(:)
    1035987  CHARACTER(LEN=*),             INTENT(IN)  :: tname(:)
    1036   TYPE(trac_type), ALLOCATABLE, INTENT(OUT) :: alias(:)
     988  TYPE(keys_type), ALLOCATABLE, INTENT(OUT) :: alias(:)
    1037989  CHARACTER(LEN=maxlen), ALLOCATABLE :: tnames(:)
    1038   lerr = getKey('name', tnames, trac(:)%keys)
     990  lerr = getKey('name', tnames, trac(:))
    1039991  alias = trac(strIdx(tnames, tname))
    1040992  lerr = indexUpdate(alias)
     
    1042994!==============================================================================================================================
    1043995LOGICAL FUNCTION trSubset_gen0Name(trac, gen0Nm, alias) RESULT(lerr)           !=== TRACERS OF COMMON 1st GENERATION ANCESTOR
    1044   TYPE(trac_type), ALLOCATABLE, INTENT(IN)  :: trac(:)
     996  TYPE(keys_type), ALLOCATABLE, INTENT(IN)  :: trac(:)
    1045997  CHARACTER(LEN=*),             INTENT(IN)  :: gen0Nm
    1046   TYPE(trac_type), ALLOCATABLE, INTENT(OUT) :: alias(:)
     998  TYPE(keys_type), ALLOCATABLE, INTENT(OUT) :: alias(:)
    1047999  CHARACTER(LEN=maxlen), ALLOCATABLE :: gen0N(:)
    1048   lerr = getKey('gen0Name', gen0N, trac(:)%keys)
     1000  lerr = getKey('gen0Name', gen0N, trac(:))
    10491001  alias = trac(strFind(delPhase(gen0N), gen0Nm))
    10501002  lerr = indexUpdate(alias)
     
    10541006
    10551007!==============================================================================================================================
    1056 !=== UPDATE THE INDEXES iqParent, iqDescend AND iGeneration IN THE TRACERS DESCRIPTOR LIST "tr" (USEFULL FOR SUBSETS) =========
     1008!=== UPDATE THE INDEXES iqParent, iqDescen, nqDescen, nqChildren IN THE TRACERS DESCRIPTOR LIST "tr" ==========================
    10571009!==============================================================================================================================
    10581010LOGICAL FUNCTION indexUpdate(tr) RESULT(lerr)
    1059   TYPE(trac_type), INTENT(INOUT) :: tr(:)
     1011  TYPE(keys_type), INTENT(INOUT) :: tr(:)
    10601012  INTEGER :: iq, jq, nq, ig, nGen
    10611013  INTEGER,               ALLOCATABLE :: iqDescen(:), ix(:), iy(:)
    10621014  CHARACTER(LEN=maxlen), ALLOCATABLE :: tnames(:), parent(:)
    10631015  INTEGER,       DIMENSION(SIZE(tr)) :: iqParent, iGen
    1064   lerr = getKey('name',   tnames, tr%keys); IF(lerr) RETURN          !--- Names
    1065   lerr = getKey('parent', parent, tr%keys); IF(lerr) RETURN          !--- Parents
     1016  lerr = getKey('name',   tnames, tr); IF(lerr) RETURN               !--- Names
     1017  lerr = getKey('parent', parent, tr); IF(lerr) RETURN               !--- Parents
    10661018  nq = SIZE(tr)
    10671019
    1068   !=== iqParent, iGeneration
     1020  !=== iqParent
    10691021  DO iq = 1, nq; iGen(iq) = 0; jq = iq
    10701022    iqParent(iq) = strIdx(tnames, parent(iq))
    10711023    DO; jq = strIdx(tnames, parent(jq)); IF(jq == 0) EXIT; iGen(iq) = iGen(iq) + 1; END DO
    1072     CALL addKey('iqParent',   parent(iq), tr(iq)%keys)
    1073     CALL addKey('iqGeneration', iGen(iq), tr(iq)%keys)
     1024    CALL addKey('iqParent', iqParent(iq), tr(iq))
    10741025  END DO
    10751026
     
    10781029  DO iq = 1, nq
    10791030    ix = [iq]; ALLOCATE(iqDescen(0))
     1031    CALL addKey('nqChildren', 0, tr(iq))
    10801032    DO ig = iGen(iq)+1, nGen
    10811033      iy = find(iqParent, ix); iqDescen = [iqDescen, iy]; ix = iy
    10821034      IF(ig /= iGen(iq)+1) CYCLE
    1083       CALL addKey('nqChildren', SIZE(iqDescen), tr(iq)%keys)
    1084       tr(iq)%nqChildren = SIZE(iqDescen)
     1035      CALL addKey('nqChildren', SIZE(iqDescen), tr(iq))
    10851036    END DO
    1086     CALL addKey('iqDescen', strStack(int2str(iqDescen)), tr(iq)%keys)
    1087     CALL addKey('nqDescen',             SIZE(iqDescen),  tr(iq)%keys)
    1088     tr(iq)%iqDescen =      iqDescen
    1089     tr(iq)%nqDescen = SIZE(iqDescen)
     1037    CALL addKey('iqDescen', strStack(int2str(iqDescen)), tr(iq))
     1038    CALL addKey('nqDescen',             SIZE(iqDescen),  tr(iq))
    10901039    DEALLOCATE(iqDescen)
    10911040  END DO
     
    10951044 
    10961045!==============================================================================================================================
    1097 !=== READ FILE "fnam" TO APPEND THE "dBase" TRACERS DATABASE WITH AS MUCH SECTIONS AS PARENTS NAMES IN "isot(:)%parent":   ====
    1098 !===  * Each section dBase(i)%name contains the isotopes "dBase(i)%trac(:)" descending on "dBase(i)%name"="iso(i)%parent"  ====
     1046!=== READ FILE "fnam" TO APPEND THE "dBase" TRACERS DATABASE WITH AS MUCH SECTIONS AS ISOTOPES CLASSES IN "isot(:)%name":  ====
     1047!===  * Each section dBase(i)%name contains the isotopes "dBase(i)%trac(:)" descending on "dBase(i)%name"="iso(i)%name"    ====
    10991048!===  * For each isotopes class, the <key>=<val> vector of each tracer is moved into the isotopes descriptor "isot"        ====
    11001049!=== NOTES:                                                                                                                ====
    11011050!===  * Most of the "isot" components have been defined in the calling routine (processIsotopes):                          ====
    1102 !===      parent,  nzone, zone(:),  niso, keys(:)%name,  ntiso, trac(:),  nphas, phas,  iqIsoPha(:,:),  itZonPhi(:,:)      ====
     1051!===      name,  nzone, zone(:),  niso, keys(:)%name,  ntiso, trac(:),  nphas, phas,  iqIsoPha(:,:),  itZonPhi(:,:)        ====
    11031052!===  * Same syntax for isotopes file and "tracer.def": a tracers section contains one line for each of its isotopes       ====
    11041053!===  * Each tracers section can contain a "params" virtual isotope line of isotopes parameters default values             ====
     
    11091058LOGICAL FUNCTION readIsotopesFile(fnam, isot) RESULT(lerr)
    11101059  CHARACTER(LEN=*),        INTENT(IN)    :: fnam                     !--- Input file name
    1111   TYPE(isot_type), TARGET, INTENT(INOUT) :: isot(:)                  !--- Isotopes descriptors (field %parent must be defined!)
     1060  TYPE(isot_type), TARGET, INTENT(INOUT) :: isot(:)                  !--- Isotopes descriptors (field %name must be defined!)
    11121061  LOGICAL :: lFound
    11131062  INTEGER :: is, iis, it, idb, ndb, nb0
    1114   CHARACTER(LEN=maxlen), ALLOCATABLE :: vals(:)
     1063  CHARACTER(LEN=maxlen), ALLOCATABLE :: vals(:), tname(:), iname(:)
    11151064  CHARACTER(LEN=maxlen)              :: modname
    1116   TYPE(trac_type),           POINTER ::   tt(:), t
     1065  TYPE(keys_type),           POINTER ::  t
    11171066  TYPE(dataBase_type),   ALLOCATABLE ::  tdb(:)
    11181067  modname = 'readIsotopesFile'
    11191068
    11201069  !--- THE INPUT FILE MUST BE PRESENT
    1121   INQUIRE(FILE=TRIM(fnam), EXIST=lFound); lerr = .NOT.lFound
    1122   IF(fmsg('Missing isotopes parameters file "'//TRIM(fnam)//'"', modname, lerr)) RETURN
    1123 
    1124   !--- READ THE FILE SECTIONS, ONE EACH PARENT TRACER
     1070  INQUIRE(FILE=TRIM(fnam), EXIST=lFound)
     1071  lerr = .NOT.lFound
     1072  CALL msg('Missing isotopes parameters file "'//TRIM(fnam)//'"', modname, lerr)
     1073  IF(lerr) RETURN
     1074
     1075  !--- READ THE FILE SECTIONS, ONE EACH ISOTOPES CLASS (FIEDL %name)
    11251076  nb0 = SIZE(dBase, DIM=1)+1                                         !--- Next database element index
    1126   lerr = readSections(fnam,strStack(isot(:)%parent,'|')); IF(lerr) RETURN !--- Read sections, one each parent tracer
     1077  lerr = readSections(fnam,strStack(isot(:)%name,'|')); IF(lerr) RETURN !--- Read sections, one each isotopes class %name
    11271078  ndb = SIZE(dBase, DIM=1)                                           !--- Current database size
    11281079  DO idb = nb0, ndb
     
    11301081
    11311082    !--- GET FEW GLOBAL KEYS FROM "def" FILES AND ADD THEM TO THE 'params' SECTION
    1132     CALL addKeysFromDef(dBase(idb)%trac, 'params')
     1083!    lerr = addKeysFromDef(dBase(idb)%trac, 'params');     IF(lerr) RETURN
    11331084
    11341085    !--- SUBSTITUTE THE KEYS DEFINED IN THE 'params' VIRTUAL TRACER ; SUBSTITUTE LOCAL KEYS ; REMOVE 'params' VIRTUAL TRACER
    1135     CALL subDefault(dBase(idb)%trac, 'params', .TRUE.)
    1136 
    1137     tt => dBase(idb)%trac
     1086    lerr = subDefault(dBase(idb)%trac, 'params', .TRUE.); IF(lerr) RETURN
    11381087
    11391088    !--- REDUCE THE EXPRESSIONS TO OBTAIN SCALARS AND TRANSFER THEM TO THE "isot" ISOTOPES DESCRIPTORS VECTOR
     1089    lerr = getKey('name', tname, dBase(idb)%trac);        IF(lerr) RETURN
     1090    lerr = getKey('name', iname, isot(iis)%keys);         IF(lerr) RETURN
    11401091    DO it = 1, SIZE(dBase(idb)%trac)
    11411092      t => dBase(idb)%trac(it)
    1142       is = strIdx(isot(iis)%keys(:)%name, t%name)                    !--- Index in "isot(iis)%keys(:)%name" of isotope "t%name"
     1093      is = strIdx(iname, tname(it))                                  !--- Index in "iname(:)" of isotope "tname(it)"
    11431094      IF(is == 0) CYCLE
    1144       lerr = ANY(reduceExpr(t%keys%val, vals)); IF(lerr) RETURN      !--- Reduce expressions ; detect non-numerical elements
    1145       isot(iis)%keys(is)%key = t%keys%key
     1095      lerr = ANY(reduceExpr(t%val, vals)); IF(lerr) RETURN           !--- Reduce expressions ; detect non-numerical elements
     1096      isot(iis)%keys(is)%key = t%key
    11461097      isot(iis)%keys(is)%val = vals
    11471098    END DO
    11481099
    11491100    !--- CHECK FOR MISSING ISOTOPES (NO KEYS ALLOCATED)
    1150     lerr = checkList(isot(iis)%keys(:)%name, .NOT.[( ALLOCATED(isot(iis)%keys(is)%key), is=1, SIZE(isot(iis)%keys) )], &
     1101    lerr = checkList(iname, .NOT.[( ALLOCATED(isot(iis)%keys(is)%key), is=1, SIZE(isot(iis)%keys) )], &
    11511102                     'Check file "'//TRIM(fnam)//'" in section "'//TRIM(dBase(idb)%name)//'"', 'isotopes', 'missing')
    11521103    IF(lerr) RETURN
     
    11611112
    11621113  !--- GET THE isoCheck ENTRY FROM THE *.DEF FILES (MIGHT BE CHANGED TO A CLASS-DEPENDANT KEYWORD)
    1163   CALL get_in('ok_iso_verif', isot(strIdx(isot%parent, 'H2O'))%check, .FALSE.)
     1114  CALL get_in('ok_iso_verif', isot(strIdx(iname, 'H2O'))%check, .FALSE.)
    11641115
    11651116  lerr = dispIsotopes()
     
    11711122  INTEGER :: ik, nk, ip, it, nt
    11721123  CHARACTER(LEN=maxlen) :: prf
    1173   CHARACTER(LEN=maxlen), ALLOCATABLE :: ttl(:), val(:,:)
     1124  CHARACTER(LEN=maxlen), ALLOCATABLE :: ttl(:), val(:,:), tname(:)
    11741125  CALL msg('Isotopes parameters read from file "'//TRIM(fnam)//'":', modname)
    1175   DO ip = 1, SIZE(isot)                                              !--- Loop on parents tracers
     1126  DO ip = 1, SIZE(isot)                                              !--- Loop on isotopes classes
     1127    IF(SIZE(isot(ip)%keys) == 0) CYCLE
    11761128    nk = SIZE(isot(ip)%keys(1)%key)                                  !--- Same keys for each isotope
    11771129    nt = SIZE(isot(ip)%keys)                                         !--- Number of isotopes
     
    11791131    ALLOCATE(ttl(nk+2), val(nt,nk+1))
    11801132    ttl(1:2) = ['it  ','name']; ttl(3:nk+2) = isot(ip)%keys(1)%key(:)!--- Titles line with keys names
    1181     val(:,1) = isot(ip)%keys(:)%name                                 !--- Values table 1st column: isotopes names 
     1133    lerr = getKey('name', tname, isot(ip)%keys); IF(lerr) RETURN
     1134    val(:,1) = tname                                                 !--- Values table 1st column: isotopes names
    11821135    DO ik = 1, nk
    11831136      DO it = 1, nt
     
    11991152!=== IF ISOTOPES (2ND GENERATION TRACERS) ARE DETECTED:                                                                     ===
    12001153!===    * COMPUTE MOST OF THE RELATED QUANTITIES ("isot" COMPONENTS).                                                       ===
    1201 !===    * COMPUTE FEW ISOTOPES-DEDICATED "trac" COMPONENTS                                                                  ===
    1202 !===    * CALL readIsotopesFile TO GET PHYSICAL QUANTITIES (<key>=<val> PAIRS)                                              ===
    1203 !===      NOTE: THIS IS DONE HERE (IN A ROUTINE CALLED BY THE DYNAMIC), BECAUSE THE DYNAMIC NEEDS FEW PHYSICAL PARAMETERS.  ===
    1204 !==============================================================================================================================
    1205 LOGICAL FUNCTION processIsotopes(iNames) RESULT(lerr)
    1206   CHARACTER(LEN=maxlen), TARGET, OPTIONAL, INTENT(IN)  :: iNames(:)
    1207   CHARACTER(LEN=maxlen), ALLOCATABLE :: p(:), str(:)                 !--- Temporary storage
    1208   CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:), parent(:), dType(:), phase(:), gen0N(:)
    1209   CHARACTER(LEN=maxlen) :: iName, modname
    1210   CHARACTER(LEN=1)   :: ph                                           !--- Phase
    1211   INTEGER, ALLOCATABLE ::  iGen(:)
    1212   INTEGER :: ic, ip, iq, it, iz
    1213   LOGICAL, ALLOCATABLE :: ll(:)                                      !--- Mask
    1214   TYPE(trac_type), POINTER   ::  t(:), t1
    1215   TYPE(isot_type), POINTER   ::  i
     1154!===    * COMPUTE FEW ISOTOPES-DEDICATED "trac" COMPONENTS (defined by "keys(:)")                                           ===
     1155!===    * CALL readIsotopesFile TO GET PHYSICAL QUANTITIES (<key>=<val> PAIRS)     /!\ DISABLED FUNCTION /!\                ===
     1156!==============================================================================================================================
     1157LOGICAL FUNCTION processIsotopes(keys, isot, iClasses) RESULT(lerr)
     1158  TYPE(keys_type),  TARGET,              OPTIONAL, INTENT(INOUT) ::   keys(:)
     1159  TYPE(isot_type),  TARGET, ALLOCATABLE, OPTIONAL, INTENT(OUT)   ::   isot(:)
     1160  CHARACTER(LEN=*), TARGET,              OPTIONAL, INTENT(IN)    :: iClasses(:)
     1161  CHARACTER(LEN=maxlen), ALLOCATABLE :: p(:), str1(:), str2(:)       !--- Temporary storage
     1162  CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:), parent(:), dType(:), phase(:), gen0N(:), iCla(:)
     1163  CHARACTER(LEN=maxlen) :: iClass, modname
     1164  CHARACTER(LEN=1)      :: ph                                           !--- Phase
     1165  LOGICAL,  ALLOCATABLE :: ll(:)                                      !--- Mask
     1166  INTEGER,  ALLOCATABLE :: iGen(:)
     1167  INTEGER :: ic, ip, iq, ii, it, iz
     1168  TYPE(isot_type), POINTER :: i1
     1169  TYPE(keys_type), POINTER :: k(:)
    12161170
    12171171  lerr = .FALSE.
    12181172  modname = 'readIsotopesFile'
    1219 
    1220   t => tracers
    1221 
    1222   lerr = getKey('name',       tname, t%keys); IF(lerr) RETURN       !--- Names
    1223   lerr = getKey('parent',    parent, t%keys); IF(lerr) RETURN       !--- Parents
    1224   lerr = getKey('type',       dType, t%keys); IF(lerr) RETURN       !--- Tracer type
    1225   lerr = getKey('phase',      phase, t%keys); IF(lerr) RETURN       !--- Phase
    1226   lerr = getKey('gen0Name',   gen0N, t%keys); IF(lerr) RETURN       !--- 1st generation ancestor name
    1227   lerr = getKey('iGeneration', iGen, t%keys); IF(lerr) RETURN       !--- Generation number
     1173  k => tracers; IF(PRESENT(keys )) k => keys
     1174  lerr = getKey('name',       tname, k); IF(lerr) RETURN             !--- Names
     1175  lerr = getKey('parent',    parent, k); IF(lerr) RETURN             !--- Parents
     1176  lerr = getKey('type',       dType, k); IF(lerr) RETURN             !--- Tracer type
     1177  lerr = getKey('phase',      phase, k); IF(lerr) RETURN             !--- Phase
     1178  lerr = getKey('gen0Name',   gen0N, k); IF(lerr) RETURN             !--- 1st generation ancestor name
     1179  lerr = getKey('iGeneration', iGen, k); IF(lerr) RETURN             !--- Generation number
     1180
     1181  !--- INITIALIZATION IF ISOTOPES-SPECIFIC KEYS (MUST BE DEFINED EVEN WITHOUT ISOTOPES)
     1182  DO iq = 1, SIZE(k)
     1183    CALL addKey('iso_iGroup',0, k(iq))                               !--- Family       idx in list "isotopes(:)%parent"
     1184    CALL addKey('iso_iName', 0, k(iq))                               !--- Isotope      idx in effective isotopes list
     1185    CALL addKey('iso_iZone', 0, k(iq))                               !--- Tagging zone idx in effective zones    list
     1186    CALL addKey('iso_iPhas', 0, k(iq))                               !--- Phase        idx in effective phases   list
     1187  END DO
    12281188
    12291189  !--- GET FROM "tracers" THE FULL LIST OF AVAILABLE ISOTOPES CLASSES
    1230   p = PACK(delPhase(parent), MASK = dType=='tracer' .AND. iGen==1)
    1231   CALL strReduce(p, nbIso)
    1232 
    1233   !--- CHECK WHETHER NEEDED ISOTOPES CLASSES "iNames" ARE AVAILABLE OR NOT
    1234   IF(PRESENT(iNames)) THEN
    1235     DO it = 1, SIZE(iNames)
    1236       lerr = ALL(p /= iNames(it))
    1237       IF(fmsg('No isotopes class "'//TRIM(iNames(it))//'" found among tracers', modname, lerr)) RETURN
     1190  iCla = PACK(delPhase(parent), MASK = dType=='tracer' .AND. iGen==1)
     1191  CALL strReduce(iCla)
     1192
     1193  !--- CHECK WHETHER NEEDED ISOTOPES CLASSES "iClasses" ARE AVAILABLE OR NOT
     1194  IF(PRESENT(iClasses)) THEN
     1195    DO it = 1, SIZE(iClasses)
     1196      lerr = ALL(iCla /= iClasses(it))
     1197      IF(fmsg('No isotopes class "'//TRIM(iClasses(it))//'" found among tracers', modname, lerr)) RETURN
    12381198    END DO
    1239     p = iNames; nbIso = SIZE(p)
     1199    iCla = iClasses
    12401200  END IF
    1241   IF(ALLOCATED(isotopes)) DEALLOCATE(isotopes)
    1242   ALLOCATE(isotopes(nbIso))
    1243 
     1201  nbIso = SIZE(iCla)
     1202
     1203  !--- USE THE ARGUMENT "isot" TO STORE THE ISOTOPIC DATABASE OR THE LOCAL VECTOR "isotopes"
     1204  IF(PRESENT(isot)) THEN
     1205    ALLOCATE(    isot(nbIso))
     1206  ELSE
     1207    IF(ALLOCATED(isotopes)) DEALLOCATE(isotopes)
     1208    ALLOCATE(isotopes(nbIso))
     1209  END IF
    12441210  IF(nbIso==0) RETURN                                                !=== NO ISOTOPES: FINISHED
    12451211
    12461212  !--- ISOTOPES RELATED VARIABLES ; NULL OR EMPTY IF NO ISOTOPES
    1247   isotopes(:)%parent = p
    1248   DO ic = 1, SIZE(p)                                                 !--- Loop on isotopes classes
    1249     i => isotopes(ic)
    1250     iname = i%parent                                                 !--- Current isotopes class name (parent tracer name)
    1251 
    1252     !=== Isotopes children of tracer "iname": mask, names, number (same for each phase of "iname")
    1253     ll = dType=='tracer' .AND. delPhase(parent) == iname .AND. phase == 'g'
    1254     str = PACK(delPhase(tname), MASK = ll)                           !--- Effectively found isotopes of "iname"
    1255     i%niso = SIZE(str)                                               !--- Number of "effectively found isotopes of "iname"
    1256     ALLOCATE(i%keys(i%niso))
    1257     FORALL(it = 1:i%niso) i%keys(it)%name = str(it)
    1258 
    1259     !=== Geographic tagging tracers descending on tracer "iname": mask, names, number
    1260     ll = dType=='tag'    .AND. delPhase(gen0N) == iname .AND. iGen == 2
    1261     i%zone = PACK(strTail(tname,'_',.TRUE.), MASK = ll)              !--- Tagging zones names  for isotopes category "iname"
    1262     CALL strReduce(i%zone)
    1263     i%nzone = SIZE(i%zone)                                           !--- Tagging zones number for isotopes category "iname"
    1264 
    1265     !=== Geographic tracers of the isotopes children of tracer "iname" (same for each phase of "iname")
     1213  DO ic = 1, nbIso                                                   !--- Loop on isotopes classes
     1214    IF(     PRESENT(isot)) i1 => isot    (ic)
     1215    IF(.NOT.PRESENT(isot)) i1 => isotopes(ic)
     1216    iClass = iCla(ic)                                                !--- Current isotopes class name (parent tracer name)
     1217    i1%name = iClass
     1218
     1219    !=== Isotopes children of tracer "iClass": mask, names, number (same for each phase of "iClass")
     1220    ll = dType=='tracer' .AND. delPhase(parent) == iClass .AND. phase == 'g'
     1221    str1 = PACK(delPhase(tname), MASK = ll)                          !--- Effectively found isotopes of "iClass"
     1222    i1%niso = SIZE(str1)                                             !--- Number of "effectively found isotopes of "iname"
     1223    ALLOCATE(i1%keys(i1%niso))
     1224    DO it = 1, i1%niso; CALL addKey('name', str1(it), i1%keys(it)); END DO
     1225
     1226    !=== Geographic tagging tracers descending on tracer "iClass": mask, names, number
     1227    ll = dType=='tag'    .AND. delPhase(gen0N) == iClass .AND. iGen == 2
     1228    i1%zone = PACK(strTail(tname, '_', .TRUE.), MASK = ll)           !--- Tagging zones names  for isotopes category "iname"
     1229    CALL strReduce(i1%zone)
     1230    i1%nzone = SIZE(i1%zone)                                         !--- Tagging zones number for isotopes category "iClass"
     1231
     1232    !=== Geographic tracers of the isotopes children of tracer "iClass" (same for each phase of "iClass")
    12661233    !    NOTE: One might like to create a similar variable for 2nd generation tagging tracers (tagging the gen1 tracers)
    1267     str = PACK(delPhase(tname), MASK=ll)
    1268     CALL strReduce(str)
    1269     i%ntiso = i%niso + SIZE(str)                                     !--- Number of isotopes + their geographic tracers [ntiso]
    1270     ALLOCATE(i%trac(i%ntiso))
    1271     FORALL(it = 1:i%niso) i%trac(it) = i%keys(it)%name
    1272     FORALL(it = i%niso+1:i%ntiso) i%trac(it) = str(it-i%niso)
    1273 
    1274     !=== Phases for tracer "iname"
    1275     i%phase = ''
    1276     DO ip = 1, nphases; ph = known_phases(ip:ip); IF(strIdx(t%name,addPhase(iname, ph)) /= 0) i%phase = TRIM(i%phase)//ph; END DO
    1277     i%nphas = LEN_TRIM(i%phase)                                       !--- Equal to "nqo" for water
     1234    str2 = PACK(delPhase(tname), MASK=ll)
     1235    CALL strReduce(str2)
     1236    i1%ntiso = i1%niso + SIZE(str2)                                  !--- Number of isotopes + their geographic tracers [ntiso]
     1237    ALLOCATE(i1%trac(i1%ntiso))
     1238    DO it =         1, i1%niso;  i1%trac(it) = str1(it);         END DO
     1239    DO it = i1%niso+1, i1%ntiso; i1%trac(it) = str2(it-i1%niso); END DO
     1240
     1241    !=== Phases for tracer "iClass"
     1242    i1%phase = ''
     1243    DO ip = 1, nphases; ph = known_phases(ip:ip); IF(ANY(tname == addPhase(iClass, ph))) i1%phase = TRIM(i1%phase)//ph; END DO
     1244    i1%nphas = LEN_TRIM(i1%phase)                                       !--- Equal to "nqo" for water
    12781245
    12791246    !=== Tables giving the index in a table of effectively found items for each dynamical tracer (1<=iq<=nqtot)
    1280     DO iq = 1, SIZE(t)
    1281       t1 => tracers(iq)
    1282       IF(delPhase(t1%gen0Name)/=iname .OR. t1%iGeneration==0) CYCLE  !--- Only deal with tracers descending on "iname"
    1283       t1%iso_iGroup = ic                                             !--- Isotopes family       idx in list "isotopes(:)%parent"
    1284       t1%iso_iName  = strIdx(i%trac, strHead(delPhase(t1%name),'_',.TRUE.)) !--- Current isotope       idx in effective isotopes list
    1285       t1%iso_iZone  = strIdx(i%zone,          strTail(t1%name, '_',.TRUE.)) !--- Current isotope zone  idx in effective zones    list
    1286       t1%iso_iPhase =  INDEX(i%phase,TRIM(t1%phase))                 !--- Current isotope phase idx in effective phases   list
    1287       IF(t1%iGeneration /= 2) t1%iso_iZone = 0                       !--- Skip possible generation 1 tagging tracers
     1247    DO iq = 1, SIZE(tracers)
     1248      ii = strIdx(i1%trac, strHead(delPhase(tname(iq)), '_', .TRUE.))
     1249      iz = strIdx(i1%zone, strTail(         tname(iq),  '_', .TRUE.))
     1250      ip =  INDEX(i1%phase,            TRIM(phase(iq)              ))
     1251      IF(delPhase(gen0N(iq)) /= iClass .OR. iGen(iq) == 0) CYCLE     !--- Only deal with tracers descending on "iClass"
     1252      CALL addKey('iso_iGroup',ic, k(iq))                            !--- Family       idx in list "isotopes(:)%name"
     1253      CALL addKey('iso_iName', ii, k(iq))                            !--- Isotope      idx in effective isotopes list
     1254      CALL addKey('iso_iZone', iz, k(iq))                            !--- Tagging zone idx in effective zones    list
     1255      CALL addKey('iso_iPhas', ip, k(iq))                            !--- Phase        idx in effective phases   list
     1256      IF(iGen(iq) /= 2) CALL addKey('iso_iZone', 0, k(iq))           !--- Skip possible generation 1 tagging tracers
    12881257    END DO
    12891258
    12901259    !=== Table used to get iq (index in dyn array, size nqtot) from the isotope and phase indexes ; the full isotopes list
    12911260    !    (including tagging tracers) is sorted this way:  iso1, iso2, ..., iso1_zone1, iso2_zone1, ..., iso1_zoneN, iso2_zoneN
    1292     i%iqIsoPha = RESHAPE( [( (strIdx(t%name,  addPhase(i%trac(it),i%phase(ip:ip))),       it=1, i%ntiso), ip=1, i%nphas)], &
    1293                          [i%ntiso, i%nphas] )
     1261    i1%iqIsoPha = RESHAPE( [( (strIdx(tname,  addPhase(i1%trac(it),i1%phase(ip:ip))),         it=1, i1%ntiso), ip=1, i1%nphas)], &
     1262                         [i1%ntiso, i1%nphas] )
    12941263    !=== Table used to get iq (index in dyn array, size nqtot) from the water and isotope and phase indexes ; the full isotopes list
    12951264    !    (including tagging tracers) is sorted this way:  iso1, iso2, ..., iso1_zone1, iso2_zone1, ..., iso1_zoneN, iso2_zoneN
    1296     i%iqWIsoPha = RESHAPE( [( [strIdx(t%name,   addPhase('H2O',i%phase(ip:ip))), i%iqIsoPha(:,ip)], ip=1,i%nphas)], &
    1297                          [1+i%ntiso, i%nphas] )
     1265    i1%iqWIsoPha = RESHAPE( [( [strIdx(tname, addPhase('H2O',      i1%phase(ip:ip))), i1%iqIsoPha(:,ip)],      ip=1, i1%nphas)], &
     1266                         [1+i1%ntiso, i1%nphas] )
    12981267    !=== Table used to get ix (index in tagging tracers isotopes list, size ntiso) from the zone and isotope indexes
    1299     i%itZonIso = RESHAPE( [( (strIdx(i%trac(:), TRIM(i%trac(it))//'_'//TRIM(i%zone(iz))), iz=1, i%nzone), it=1, i%niso )], &
    1300                          [i%nzone, i%niso] )
     1268    i1%itZonIso = RESHAPE( [( (strIdx(i1%trac(:), TRIM(i1%trac(it))//'_'//TRIM(i1%zone(iz))), iz=1, i1%nzone), it=1, i1%niso )], &
     1269                         [i1%nzone, i1%niso] )
    13011270  END DO
    13021271
    1303   !=== READ PHYSICAL PARAMETERS FROM isoFile FILE
    1304 !  lerr = readIsotopesFile(isoFile, isotopes); IF(lerr) RETURN! on commente pour ne pas chercher isotopes_params.def
     1272  !=== READ PHYSICAL PARAMETERS FROM isoFile FILE (COMMENTED => DISABLED)
     1273!  IF(     PRESENT(isot)) lerr = readIsotopesFile(isoFile, isot)
     1274!  IF(.NOT.PRESENT(isot)) lerr = readIsotopesFile(isoFile, isotopes)
     1275!  IF(lerr) RETURN
    13051276
    13061277  !--- GET THE isoCheck ENTRY FROM THE *.DEF FILES (MIGHT BE CHANGED TO A CLASS-DEPENDANT KEYWORD)
     
    13111282
    13121283  !=== SELECT WATER ISOTOPES CLASS OR, IF UNFOUND, THE FIRST ISOTOPES CLASS
    1313   IF(isoSelect('H2O', .TRUE.)) THEN; iH2O = ixIso; ELSE; lerr = isoSelect(1, .TRUE.); END IF
     1284  IF(isoSelect('H2O', lVerbose=.TRUE.)) THEN
     1285    iH2O = ixIso
     1286  ELSE
     1287    lerr = isoSelect(1, lVerbose=.TRUE.)
     1288  END IF
    13141289
    13151290CONTAINS
     
    13191294!------------------------------------------------------------------------------------------------------------------------------
    13201295  INTEGER :: ix, it, ip, np, iz, nz, npha, nzon
    1321   TYPE(isot_type), POINTER :: i
    13221296  DO ix = 1, nbIso
    1323     i => isotopes(ix)
     1297    IF(     PRESENT(isot)) i1 => isot    (ix)
     1298    IF(.NOT.PRESENT(isot)) i1 => isotopes(ix)
    13241299    !--- Check whether each isotope and tagging isotopic tracer is present in the same number of phases
    1325     DO it = 1, i%ntiso; npha = i%nphas
    1326       np = SUM([(COUNT(tracers(:)%name == addPhase(i%trac(it), i%phase(ip:ip))), ip=1, npha)])
     1300    DO it = 1, i1%ntiso; npha = i1%nphas
     1301      np = SUM([(COUNT(tname(:) == addPhase(i1%trac(it), i1%phase(ip:ip))), ip=1, npha)])
    13271302      lerr = np /= npha
    1328       CALL msg(TRIM(int2str(np))//' phases instead of '//TRIM(int2str(npha))//' for '//TRIM(i%trac(it)), modname, lerr)
     1303      CALL msg(TRIM(int2str(np))//       ' phases instead of '//TRIM(int2str(npha))//' for '//TRIM(i1%trac(it)), modname, lerr)
    13291304      IF(lerr) RETURN
    13301305    END DO
    1331     DO it = 1, i%niso; nzon = i%nzone
    1332       nz = SUM([(COUNT(i%trac == TRIM(i%trac(it))//'_'//i%zone(iz)), iz=1, nzon)])
     1306    DO it = 1, i1%niso; nzon = i1%nzone
     1307      nz = SUM([(COUNT(i1%trac == TRIM(i1%trac(it))//'_'//i1%zone(iz)), iz=1, nzon)])
    13331308      lerr = nz /= nzon
    1334       CALL msg(TRIM(int2str(nz))//' tagging zones instead of '//TRIM(int2str(nzon))//' for '//TRIM(i%trac(it)), modname, lerr)
     1309      CALL msg(TRIM(int2str(nz))//' tagging zones instead of '//TRIM(int2str(nzon))//' for '//TRIM(i1%trac(it)), modname, lerr)
    13351310      IF(lerr) RETURN
    13361311    END DO
     
    13451320!==============================================================================================================================
    13461321!=== THE ROUTINE isoSelect IS USED TO SWITCH FROM AN ISOTOPE FAMILY TO ANOTHER: ISOTOPES DEPENDENT PARAMETERS ARE UPDATED
    1347 !     Single generic "isoSelect" routine, using the predefined index of the parent (fast version) or its name (first call).
    1348 !==============================================================================================================================
    1349 LOGICAL FUNCTION isoSelectByName(iName, lVerbose) RESULT(lerr)
     1322!     Single generic "isoSelect" routine, using the predefined index of the class (fast version) or its name (first call).
     1323!==============================================================================================================================
     1324LOGICAL FUNCTION isoSelectByName(iClass, isot, lVerbose) RESULT(lerr)
    13501325   IMPLICIT NONE
    1351    CHARACTER(LEN=*),  INTENT(IN) :: iName
    1352    LOGICAL, OPTIONAL, INTENT(IN) :: lVerbose
     1326   CHARACTER(LEN=*),                  INTENT(IN) :: iClass
     1327   TYPE(isot_type), OPTIONAL, TARGET, INTENT(IN) :: isot(:)
     1328   LOGICAL,         OPTIONAL,         INTENT(IN) :: lVerbose
     1329   TYPE(isot_type), POINTER :: iso(:)
    13531330   INTEGER :: iIso
    13541331   LOGICAL :: lV
    1355    lV = .FALSE.; IF(PRESENT(lVerbose)) lV = lVerbose
    1356    iIso = strIdx(isotopes(:)%parent, iName)
     1332   lV = .FALSE.;    IF(PRESENT(lVerbose)) lV = lVerbose
     1333   iso => isotopes; IF(PRESENT(isot))    iso => isot
     1334   iIso = strIdx(iso(:)%name, iClass)
    13571335   lerr = iIso == 0
    13581336   IF(lerr) THEN
    13591337      niso = 0; ntiso = 0; nzone = 0; nphas = 0; isoCheck=.FALSE.
    1360       CALL msg('no isotope family named "'//TRIM(iName)//'"', ll=lV)
     1338      CALL msg('no isotope family named "'//TRIM(iClass)//'"', ll=lV)
    13611339      RETURN
    13621340   END IF
    1363    lerr = isoSelectByIndex(iIso, lV)
     1341   lerr = isoSelectByIndex(iIso, iso, lV)
    13641342END FUNCTION isoSelectByName
    13651343!==============================================================================================================================
    1366 LOGICAL FUNCTION isoSelectByIndex(iIso, lVerbose) RESULT(lerr)
     1344LOGICAL FUNCTION isoSelectByIndex(iIso, isot, lVerbose) RESULT(lerr)
    13671345   IMPLICIT NONE
    1368    INTEGER,           INTENT(IN) :: iIso
    1369    LOGICAL, OPTIONAL, INTENT(IN) :: lVerbose
     1346   INTEGER,                           INTENT(IN)    :: iIso
     1347   TYPE(isot_type), TARGET, OPTIONAL, INTENT(INOUT) :: isot(:)
     1348   LOGICAL,                 OPTIONAL, INTENT(IN)    :: lVerbose
     1349   TYPE(isot_type), POINTER :: i(:)
    13701350   LOGICAL :: lV
    1371    lv = .FALSE.; IF(PRESENT(lVerbose)) lv = lVerbose
     1351   lV = .FALSE.;  IF(PRESENT(lVerbose)) lV = lVerbose
     1352   i => isotopes; IF(PRESENT(isot))      i => isot
    13721353   lerr = .FALSE.
    13731354   IF(iIso == ixIso) RETURN                                          !--- Nothing to do if the index is already OK
    1374    lerr = iIso<=0 .OR. iIso>SIZE(isotopes)
     1355   lerr = iIso<=0 .OR. iIso>SIZE(i)
    13751356   CALL msg('Inconsistent isotopes family index '//TRIM(int2str(iIso))//': should be > 0 and <= '&
    1376           //TRIM(int2str(SIZE(isotopes)))//'"', ll = lerr .AND. lV)
     1357          //TRIM(int2str(SIZE(i)))//'"', ll = lerr .AND. lV)
    13771358   IF(lerr) RETURN
    13781359   ixIso = iIso                                                      !--- Update currently selected family index
    1379    isotope  => isotopes(ixIso)                                       !--- Select corresponding component
     1360   isotope  => i(ixIso)                                              !--- Select corresponding component
    13801361   isoKeys  => isotope%keys;     niso     = isotope%niso
    13811362   isoName  => isotope%trac;     ntiso    = isotope%ntiso
     
    13841365   itZonIso => isotope%itZonIso; isoCheck = isotope%check
    13851366   iqIsoPha => isotope%iqIsoPha
    1386    iqWIsoPha => isotope%iqWIsoPha
     1367   iqWIsoPha=> isotope%iqWIsoPha
    13871368END FUNCTION isoSelectByIndex
    13881369!==============================================================================================================================
     
    15281509!=== OVERWRITE THE KEYS OF THE TRACER NAMED "tr0" WITH THE VALUES FOUND IN THE *.def FILES, IF ANY. ===========================
    15291510!==============================================================================================================================
    1530 SUBROUTINE addKeysFromDef(t, tr0)
    1531   TYPE(trac_type), ALLOCATABLE, INTENT(INOUT) :: t(:)
     1511LOGICAL FUNCTION addKeysFromDef(t, tr0) RESULT(lerr)
     1512  TYPE(keys_type), ALLOCATABLE, INTENT(INOUT) :: t(:)
    15321513  CHARACTER(LEN=*),             INTENT(IN)    :: tr0
    15331514!------------------------------------------------------------------------------------------------------------------------------
     1515  CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:)
    15341516  CHARACTER(LEN=maxlen) :: val
    15351517  INTEGER               :: ik, jd
    1536   jd = strIdx(t%name, tr0)
     1518  lerr = getKey('name', tname, t); IF(lerr) RETURN
     1519  jd = strIdx(tname(:), tr0)
    15371520  IF(jd == 0) RETURN
    1538   DO ik = 1, SIZE(t(jd)%keys%key)
    1539     CALL get_in(t(jd)%keys%key(ik), val, '*none*')
    1540     IF(val /= '*none*') CALL addKey(t(jd)%keys%key(ik), val, t(jd)%keys, .TRUE.)
     1521  DO ik = 1, SIZE(t(jd)%key)
     1522    CALL get_in(t(jd)%key(ik), val, '*none*')
     1523    IF(val /= '*none*') CALL addKey(t(jd)%key(ik), val, t(jd), .TRUE.)
    15411524  END DO
    1542 END SUBROUTINE addKeysFromDef
     1525END FUNCTION addKeysFromDef
    15431526!==============================================================================================================================
    15441527
     
    15501533  INTEGER,          INTENT(IN)    :: itr
    15511534  CHARACTER(LEN=*), INTENT(IN)    :: keyn(:)
    1552   TYPE(trac_type),  INTENT(INOUT) :: ky(:)
     1535  TYPE(keys_type),  INTENT(INOUT) :: ky(:)
    15531536!------------------------------------------------------------------------------------------------------------------------------
    15541537  CHARACTER(LEN=maxlen), ALLOCATABLE :: k(:), v(:)
     
    15561539  INTEGER :: iky
    15571540  IF(itr<=0 .OR. itr>SIZE(ky, DIM=1)) RETURN                          !--- Index is out of range
    1558   ll = [( ALL(keyn/=ky(itr)%keys%key(iky)), iky=1, SIZE(ky(itr)%keys%key) )]
    1559   k = PACK(ky(itr)%keys%key, MASK=ll); CALL MOVE_ALLOC(FROM=k, TO=ky(itr)%keys%key)
    1560   v = PACK(ky(itr)%keys%val, MASK=ll); CALL MOVE_ALLOC(FROM=v, TO=ky(itr)%keys%val)
     1541  ll = [( ALL(keyn/=ky(itr)%key(iky)), iky=1, SIZE(ky(itr)%key) )]
     1542  k = PACK(ky(itr)%key, MASK=ll); CALL MOVE_ALLOC(FROM=k, TO=ky(itr)%key)
     1543  v = PACK(ky(itr)%val, MASK=ll); CALL MOVE_ALLOC(FROM=v, TO=ky(itr)%val)
    15611544END SUBROUTINE delKey_1
    15621545!==============================================================================================================================
    15631546SUBROUTINE delKey(keyn, ky)
    15641547  CHARACTER(LEN=*), INTENT(IN)    :: keyn(:)
    1565   TYPE(trac_type),  INTENT(INOUT) :: ky(:)
     1548  TYPE(keys_type),  INTENT(INOUT) :: ky(:)
    15661549!------------------------------------------------------------------------------------------------------------------------------
    15671550  INTEGER :: iky
     
    16111594!=== TRY TO GET THE KEY NAMED "key" FOR THE "itr"th TRACER IN:                                                              ===
    16121595!===  * ARGUMENT "ky" DATABASE IF SPECIFIED ; OTHERWISE:                                                                    ===
    1613 !===  * IN INTERNAL TRACERS DATABASE "tracers(:)%keys" (IF UNFOUND, IN INTERNAL ISOTOPES DATABASE "isotope%keys(:)")        ===
     1596!===  * IN INTERNAL TRACERS DATABASE "tracers(:)" (IF UNFOUND, IN INTERNAL ISOTOPES DATABASE "isotope%keys(:)")             ===
    16141597!=== THE RETURNED VALUE (STRING, AN INTEGER, A REAL OR A LOGICAL) CAN BE EITHER:                                            ===
    16151598!===  * A SCALAR                                                                                                            ===
     
    16771660  lerr = .TRUE.
    16781661  IF(lerr .AND. PRESENT(ky))         val = fgetKey(ky)                                   !--- "ky"
    1679   IF(lerr .AND. ALLOCATED (tracers)) val = fgetKey(tracers(:)%keys)                      !--- "tracers"
     1662  IF(lerr .AND. ALLOCATED (tracers)) val = fgetKey(tracers(:))                           !--- "tracers"
    16801663  IF(lerr .AND. ASSOCIATED(isotope)) val = fgetKey(isotope%keys(:))                      !--- "isotope"
    16811664  IF(lerr .AND. PRESENT(def)) THEN
     
    17821765  IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN
    17831766  val = str2int(svals)
    1784   lerr = ANY(val == -HUGE(1))
     1767  lerr = ANY(val == -HUGE(1)) .AND. sval /= ''
    17851768  s = 'key "'//TRIM(keyn)//'" of tracer nr. '//TRIM(int2str(itr))//' is not'
    17861769  CALL msg(TRIM(s)//' an integer: '//TRIM(sval), modname, lerr)
     
    18021785  IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN
    18031786  val = str2real(svals)
    1804   lerr = ANY(val == -HUGE(1.))
     1787  lerr = ANY(val == -HUGE(1.)) .AND. sval /= ''
    18051788  s = 'key "'//TRIM(keyn)//'" of tracer nr. '//TRIM(int2str(itr))//' is not'
    18061789  CALL msg(TRIM(s)//' a real: '//TRIM(sval), modname, lerr)
     
    18231806  IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN
    18241807  ivals = str2bool(svals)
    1825   lerr = ANY(ivals == -1)
     1808  lerr = ANY(ivals == -1) .AND. sval /= ''
    18261809  s = 'key "'//TRIM(keyn)//'" of tracer nr. '//TRIM(int2str(itr))//' is not'
    18271810  CALL msg(TRIM(s)//' a boolean: '//TRIM(sval), modname, lerr)
     
    18601843  IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN
    18611844  val = str2int(svals)
    1862   lerr = ANY(val == -HUGE(1))
     1845  lerr = ANY(val == -HUGE(1)) .AND. sval /= ''
    18631846  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of tracer nr. '//TRIM(int2str(itr))//' is not'
    18641847  CALL msg(TRIM(s)//' an integer: '//TRIM(sval), modname, lerr)
     
    18811864  IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN
    18821865  val = str2real(svals)
    1883   lerr = ANY(val == -HUGE(1.))
     1866  lerr = ANY(val == -HUGE(1.)) .AND. sval /= ''
    18841867  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of tracer nr. '//TRIM(int2str(itr))//' is not'
    18851868  CALL msg(TRIM(s)//' a real: '//TRIM(sval), modname, lerr)
     
    19031886  IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN
    19041887  ivals = str2bool(svals)
    1905   lerr = ANY(ivals == -1)
     1888  lerr = ANY(ivals == -1) .AND. sval /= ''
    19061889  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of tracer nr. '//TRIM(int2str(itr))//' is not'
    19071890  CALL msg(TRIM(s)//' a boolean: '//TRIM(sval), modname, lerr)
     
    19101893!==============================================================================================================================
    19111894!==============================================================================================================================
    1912 LOGICAL FUNCTION getKeyByIndex_s1mm(keyn, val, ky, nam, def, lDisp) RESULT(lerr)
    1913   CHARACTER(LEN=*),                             INTENT(IN)  :: keyn
    1914   CHARACTER(LEN=maxlen),           ALLOCATABLE, INTENT(OUT) :: val(:)
    1915   TYPE(keys_type),       OPTIONAL,              INTENT(IN)  ::  ky(:)
    1916   CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: nam(:)
    1917   CHARACTER(LEN=*),      OPTIONAL,              INTENT(IN)  :: def
    1918   LOGICAL,               OPTIONAL,              INTENT(IN)  :: lDisp
    1919   lerr = getKeyByIndex_smmm([keyn], val, ky, nam, def, lDisp)
     1895LOGICAL FUNCTION getKeyByIndex_s1mm(keyn, val, ky, def, lDisp) RESULT(lerr)
     1896  CHARACTER(LEN=*),                   INTENT(IN)  :: keyn
     1897  CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) :: val(:)
     1898  TYPE(keys_type),       OPTIONAL,    INTENT(IN)  ::  ky(:)
     1899  CHARACTER(LEN=*),      OPTIONAL,    INTENT(IN)  :: def
     1900  LOGICAL,               OPTIONAL,    INTENT(IN)  :: lDisp
     1901  lerr = getKeyByIndex_smmm([keyn], val, ky, def, lDisp)
    19201902END FUNCTION getKeyByIndex_s1mm
    19211903!==============================================================================================================================
    1922 LOGICAL FUNCTION getKeyByIndex_i1mm(keyn, val, ky, nam, def, lDisp) RESULT(lerr)
    1923   CHARACTER(LEN=*),                             INTENT(IN)  :: keyn
    1924   INTEGER,                         ALLOCATABLE, INTENT(OUT) :: val(:)
    1925   TYPE(keys_type),       OPTIONAL,              INTENT(IN)  ::  ky(:)
    1926   CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: nam(:)
    1927   INTEGER,               OPTIONAL,              INTENT(IN)  :: def
    1928   LOGICAL,               OPTIONAL,              INTENT(IN)  :: lDisp
    1929   lerr = getKeyByIndex_immm([keyn], val, ky, nam, def, lDisp)
     1904LOGICAL FUNCTION getKeyByIndex_i1mm(keyn, val, ky, def, lDisp) RESULT(lerr)
     1905  CHARACTER(LEN=*),                   INTENT(IN)  :: keyn
     1906  INTEGER,               ALLOCATABLE, INTENT(OUT) :: val(:)
     1907  TYPE(keys_type),       OPTIONAL,    INTENT(IN)  ::  ky(:)
     1908  INTEGER,               OPTIONAL,    INTENT(IN)  :: def
     1909  LOGICAL,               OPTIONAL,    INTENT(IN)  :: lDisp
     1910  lerr = getKeyByIndex_immm([keyn], val, ky, def, lDisp)
    19301911END FUNCTION getKeyByIndex_i1mm
    19311912!==============================================================================================================================
    1932 LOGICAL FUNCTION getKeyByIndex_r1mm(keyn, val, ky, nam, def, lDisp) RESULT(lerr)
    1933   CHARACTER(LEN=*),                             INTENT(IN)  :: keyn
    1934   REAL,                            ALLOCATABLE, INTENT(OUT) :: val(:)
    1935   TYPE(keys_type),       OPTIONAL,              INTENT(IN)  ::  ky(:)
    1936   CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: nam(:)
    1937   REAL,                  OPTIONAL,              INTENT(IN)  :: def
    1938   LOGICAL,               OPTIONAL,              INTENT(IN)  :: lDisp
    1939   lerr = getKeyByIndex_rmmm([keyn], val, ky, nam, def, lDisp)
     1913LOGICAL FUNCTION getKeyByIndex_r1mm(keyn, val, ky, def, lDisp) RESULT(lerr)
     1914  CHARACTER(LEN=*),                   INTENT(IN)  :: keyn
     1915  REAL,                  ALLOCATABLE, INTENT(OUT) :: val(:)
     1916  TYPE(keys_type),       OPTIONAL,    INTENT(IN)  ::  ky(:)
     1917  REAL,                  OPTIONAL,    INTENT(IN)  :: def
     1918  LOGICAL,               OPTIONAL,    INTENT(IN)  :: lDisp
     1919  lerr = getKeyByIndex_rmmm([keyn], val, ky, def, lDisp)
    19401920END FUNCTION getKeyByIndex_r1mm
    19411921!==============================================================================================================================
    1942 LOGICAL FUNCTION getKeyByIndex_l1mm(keyn, val, ky, nam, def, lDisp) RESULT(lerr)
    1943   CHARACTER(LEN=*),                             INTENT(IN)  :: keyn
    1944   LOGICAL,                         ALLOCATABLE, INTENT(OUT) :: val(:)
    1945   TYPE(keys_type),       OPTIONAL,              INTENT(IN)  ::  ky(:)
    1946   CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: nam(:)
    1947   LOGICAL,               OPTIONAL,              INTENT(IN)  :: def
    1948   LOGICAL,               OPTIONAL,              INTENT(IN)  :: lDisp
    1949   lerr = getKeyByIndex_lmmm([keyn], val, ky, nam, def, lDisp)
     1922LOGICAL FUNCTION getKeyByIndex_l1mm(keyn, val, ky, def, lDisp) RESULT(lerr)
     1923  CHARACTER(LEN=*),                   INTENT(IN)  :: keyn
     1924  LOGICAL,               ALLOCATABLE, INTENT(OUT) :: val(:)
     1925  TYPE(keys_type),       OPTIONAL,    INTENT(IN)  ::  ky(:)
     1926  LOGICAL,               OPTIONAL,    INTENT(IN)  :: def
     1927  LOGICAL,               OPTIONAL,    INTENT(IN)  :: lDisp
     1928  lerr = getKeyByIndex_lmmm([keyn], val, ky, def, lDisp)
    19501929END FUNCTION getKeyByIndex_l1mm
    19511930!==============================================================================================================================
    19521931!==============================================================================================================================
    1953 LOGICAL FUNCTION getKeyByIndex_smmm(keyn, val, ky, nam, def, lDisp) RESULT(lerr)
    1954   CHARACTER(LEN=*),                             INTENT(IN)  :: keyn(:)
    1955   CHARACTER(LEN=maxlen),           ALLOCATABLE, INTENT(OUT) ::  val(:)
    1956   TYPE(keys_type),       OPTIONAL,              INTENT(IN)  ::   ky(:)
    1957   CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) ::  nam(:)
    1958   CHARACTER(LEN=*),      OPTIONAL,              INTENT(IN)  ::  def
    1959   LOGICAL,               OPTIONAL,              INTENT(IN)  :: lDisp
     1932LOGICAL FUNCTION getKeyByIndex_smmm(keyn, val, ky, def, lDisp) RESULT(lerr)
     1933  CHARACTER(LEN=*),                   INTENT(IN)  :: keyn(:)
     1934  CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) ::  val(:)
     1935  TYPE(keys_type),       OPTIONAL,    INTENT(IN)  ::   ky(:)
     1936  CHARACTER(LEN=*),      OPTIONAL,    INTENT(IN)  ::  def
     1937  LOGICAL,               OPTIONAL,    INTENT(IN)  :: lDisp
    19601938!------------------------------------------------------------------------------------------------------------------------------
    19611939  CHARACTER(LEN=maxlen) :: s
    1962   CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:)
    19631940  INTEGER :: iq, nq(3), k
    19641941  LOGICAL :: lD, l(3)
     
    19671944  lerr = .TRUE.
    19681945  IF(PRESENT(ky)) THEN;                 val = fgetKey(ky)                                !--- "ky"
    1969   ELSE IF(ALLOCATED(tracers)) THEN;     val = fgetKey(tracers(:)%keys)                   !--- "tracers"
     1946  ELSE IF(ALLOCATED(tracers)) THEN;     val = fgetKey(tracers(:))                        !--- "tracers"
    19701947     IF(lerr .AND. ASSOCIATED(isotope)) val = fgetKey(isotope%keys(:))                   !--- "isotope"
    19711948  END IF
    1972   IF(.NOT.lerr) THEN; IF(PRESENT(nam)) nam = tname; RETURN; END IF
     1949  IF(.NOT.lerr) RETURN
    19731950  IF(.NOT.PRESENT(def)) THEN; CALL msg('No '//TRIM(s)//' found', modname, lD); RETURN; END IF
    19741951
     
    19911968  INTEGER :: iq
    19921969  lerr = SIZE(ky) == 0; IF(lerr) RETURN
    1993   tname = ky%name
    19941970  val = [(fgetKeyIdx(iq, keyn(:), ky, ler(iq)), iq = 1, SIZE(ky))]
    19951971  lerr = ANY(ler)
     
    19981974END FUNCTION getKeyByIndex_smmm
    19991975!==============================================================================================================================
    2000 LOGICAL FUNCTION getKeyByIndex_immm(keyn, val, ky, nam, def, lDisp) RESULT(lerr)
    2001   CHARACTER(LEN=*),                             INTENT(IN)  :: keyn(:)
    2002   INTEGER,                         ALLOCATABLE, INTENT(OUT) ::  val(:)
    2003   TYPE(keys_type),       OPTIONAL,              INTENT(IN)  ::   ky(:)
    2004   CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) ::  nam(:)
    2005   INTEGER,               OPTIONAL,              INTENT(IN)  ::  def
    2006   LOGICAL,               OPTIONAL,              INTENT(IN)  :: lDisp
     1976LOGICAL FUNCTION getKeyByIndex_immm(keyn, val, ky, def, lDisp) RESULT(lerr)
     1977  CHARACTER(LEN=*),          INTENT(IN)  :: keyn(:)
     1978  INTEGER,      ALLOCATABLE, INTENT(OUT) ::  val(:)
     1979  TYPE(keys_type), OPTIONAL, INTENT(IN)  ::   ky(:)
     1980  INTEGER,         OPTIONAL, INTENT(IN)  ::  def
     1981  LOGICAL,         OPTIONAL, INTENT(IN)  :: lDisp
    20071982!------------------------------------------------------------------------------------------------------------------------------
    20081983  CHARACTER(LEN=maxlen) :: s
    20091984  CHARACTER(LEN=maxlen), ALLOCATABLE :: svals(:), tname(:)
    20101985  LOGICAL,               ALLOCATABLE ::    ll(:)
    2011   IF(     PRESENT(def)) lerr = getKeyByIndex_smmm(keyn, svals, ky, tname, int2str(def), lDisp)
    2012   IF(.NOT.PRESENT(def)) lerr = getKeyByIndex_smmm(keyn, svals, ky, tname, lDisp=lDisp)
     1986  IF(     PRESENT(def)) lerr = getKeyByIndex_smmm(keyn, svals, ky, int2str(def), lDisp)
     1987  IF(.NOT.PRESENT(def)) lerr = getKeyByIndex_smmm(keyn, svals, ky, lDisp=lDisp)
    20131988  IF(lerr) RETURN
    20141989  val = str2int(svals)
    2015   ll = val == -HUGE(1)
    2016   lerr = ANY(ll); IF(.NOT.lerr) THEN; IF(PRESENT(nam)) nam = tname; RETURN; END IF
     1990  ll = val == -HUGE(1) .AND. (SIZE(svals) /=1 .OR. svals(1) /= '')
     1991  lerr = ANY(ll); IF(.NOT.lerr) RETURN
     1992  IF(getKeyByIndex_smmm(['name'], tname, ky)) RETURN
    20171993  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(strStack(PACK(tname, MASK=ll)))//' is not'
    20181994  CALL msg(TRIM(s)//' an integer: '//TRIM(strStack(svals, MASK=ll)), modname, lerr)
    2019   IF(.NOT.lerr .AND. PRESENT(nam)) nam = tname
    20201995END FUNCTION getKeyByIndex_immm
    20211996!==============================================================================================================================
    2022 LOGICAL FUNCTION getKeyByIndex_rmmm(keyn, val, ky, nam, def, lDisp) RESULT(lerr)
    2023   CHARACTER(LEN=*),                             INTENT(IN)  :: keyn(:)
    2024   REAL,                            ALLOCATABLE, INTENT(OUT) ::  val(:)
    2025   TYPE(keys_type),       OPTIONAL,              INTENT(IN)  ::   ky(:)
    2026   CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) ::  nam(:)
    2027   REAL,                  OPTIONAL,              INTENT(IN)  ::  def
    2028   LOGICAL,               OPTIONAL,              INTENT(IN)  :: lDisp
     1997LOGICAL FUNCTION getKeyByIndex_rmmm(keyn, val, ky, def, lDisp) RESULT(lerr)
     1998  CHARACTER(LEN=*),          INTENT(IN)  :: keyn(:)
     1999  REAL,         ALLOCATABLE, INTENT(OUT) ::  val(:)
     2000  TYPE(keys_type), OPTIONAL, INTENT(IN)  ::   ky(:)
     2001  REAL,            OPTIONAL, INTENT(IN)  ::  def
     2002  LOGICAL,         OPTIONAL, INTENT(IN)  :: lDisp
    20292003!------------------------------------------------------------------------------------------------------------------------------
    20302004  CHARACTER(LEN=maxlen) :: s
    20312005  CHARACTER(LEN=maxlen), ALLOCATABLE :: svals(:), tname(:)
    20322006  LOGICAL,               ALLOCATABLE ::    ll(:)
    2033   IF(     PRESENT(def)) lerr = getKeyByIndex_smmm(keyn, svals, ky, tname, real2str(def), lDisp)
    2034   IF(.NOT.PRESENT(def)) lerr = getKeyByIndex_smmm(keyn, svals, ky, tname, lDisp=lDisp)
     2007  IF(     PRESENT(def)) lerr = getKeyByIndex_smmm(keyn, svals, ky, real2str(def), lDisp)
     2008  IF(.NOT.PRESENT(def)) lerr = getKeyByIndex_smmm(keyn, svals, ky, lDisp=lDisp)
    20352009  IF(lerr) RETURN
    20362010  val = str2real(svals)
    2037   ll = val == -HUGE(1.)
    2038   lerr = ANY(ll); IF(.NOT.lerr) THEN; IF(PRESENT(nam)) nam = tname; RETURN; END IF
     2011  ll = val == -HUGE(1.) .AND. (SIZE(svals) /=1 .OR. svals(1) /= '')
     2012  lerr = ANY(ll); IF(.NOT.lerr) RETURN
     2013  IF(getKeyByIndex_smmm(['name'], tname, ky)) RETURN
    20392014  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(strStack(PACK(tname, MASK=ll)))//' is not a'
    20402015  CALL msg(TRIM(s)//' a real: '//TRIM(strStack(svals, MASK=ll)), modname)
    20412016END FUNCTION getKeyByIndex_rmmm
    20422017!==============================================================================================================================
    2043 LOGICAL FUNCTION getKeyByIndex_lmmm(keyn, val, ky, nam, def, lDisp) RESULT(lerr)
    2044   CHARACTER(LEN=*),                             INTENT(IN)  :: keyn(:)
    2045   LOGICAL,                         ALLOCATABLE, INTENT(OUT) ::  val(:)
    2046   TYPE(keys_type),       OPTIONAL,              INTENT(IN)  ::   ky(:)
    2047   CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) ::  nam(:)
    2048   LOGICAL,               OPTIONAL,              INTENT(IN)  ::  def
    2049   LOGICAL,               OPTIONAL,              INTENT(IN)  :: lDisp
     2018LOGICAL FUNCTION getKeyByIndex_lmmm(keyn, val, ky, def, lDisp) RESULT(lerr)
     2019  CHARACTER(LEN=*),          INTENT(IN)  :: keyn(:)
     2020  LOGICAL,      ALLOCATABLE, INTENT(OUT) ::  val(:)
     2021  TYPE(keys_type), OPTIONAL, INTENT(IN)  ::   ky(:)
     2022  LOGICAL,         OPTIONAL, INTENT(IN)  ::  def
     2023  LOGICAL,         OPTIONAL, INTENT(IN)  :: lDisp
    20502024!------------------------------------------------------------------------------------------------------------------------------
    20512025  CHARACTER(LEN=maxlen) :: s
     
    20532027  LOGICAL,               ALLOCATABLE ::    ll(:)
    20542028  INTEGER,               ALLOCATABLE :: ivals(:)
    2055   IF(     PRESENT(def)) lerr = getKeyByIndex_smmm(keyn, svals, ky, tname, bool2str(def), lDisp)
    2056   IF(.NOT.PRESENT(def)) lerr = getKeyByIndex_smmm(keyn, svals, ky, tname, lDisp=lDisp)
     2029  IF(     PRESENT(def)) lerr = getKeyByIndex_smmm(keyn, svals, ky, bool2str(def), lDisp)
     2030  IF(.NOT.PRESENT(def)) lerr = getKeyByIndex_smmm(keyn, svals, ky, lDisp=lDisp)
    20572031  IF(lerr) RETURN
    20582032  ivals = str2bool(svals)
    2059   ll = ivals == -1
    2060   lerr = ANY(ll); IF(.NOT.lerr) THEN; val = ivals == 1; IF(PRESENT(nam)) nam = tname; RETURN; END IF
     2033  ll = ivals == -1 .AND. (SIZE(svals) /=1 .OR. svals(1) /= '')
     2034  lerr = ANY(ll); IF(.NOT.lerr) RETURN
     2035  IF(getKeyByIndex_smmm(['name'], tname, ky)) RETURN
    20612036  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(strStack(tname, MASK=ll))//' is not'
    20622037  CALL msg(TRIM(s)//' a boolean: '//TRIM(strStack(svals, MASK=ll)), modname)
     
    20712046!=== TRY TO GET THE KEY NAMED "key" FOR THE TRACER NAMED "tname" IN:                                                        ===
    20722047!===  * ARGUMENT "ky" DATABASE IF SPECIFIED ; OTHERWISE:                                                                    ===
    2073 !===  * IN INTERNAL TRACERS DATABASE "tracers(:)%keys" (IF UNFOUND, IN INTERNAL ISOTOPES DATABASE "isotope%keys(:)")        ===
     2048!===  * IN INTERNAL TRACERS DATABASE "tracers(:)" (IF UNFOUND, IN INTERNAL ISOTOPES DATABASE "isotope%keys(:)")             ===
    20742049!=== THE RETURNED VALUE (STRING, AN INTEGER, A REAL OR A LOGICAL) CAN BE EITHER:                                            ===
    20752050!===  * A SCALAR                                                                                                            ===
     
    21332108  tnam = strHead(delPhase(tname),'_',.TRUE.)                                             !--- Remove phase and tag
    21342109  IF(lerr .AND. PRESENT(ky))         val = fgetKey(ky)                                   !--- "ky"
    2135   IF(lerr .AND. ALLOCATED (tracers)) val = fgetKey(tracers(:)%keys)                      !--- "tracers"
     2110  IF(lerr .AND. ALLOCATED (tracers)) val = fgetKey(tracers(:))                           !--- "tracers"
    21362111  IF(lerr .AND. ASSOCIATED(isotope)) val = fgetKey(isotope%keys(:))                      !--- "isotope"
    21372112  IF(lerr .AND. PRESENT(def)) THEN
     
    21452120 CHARACTER(LEN=maxlen) FUNCTION fgetKey(ky) RESULT(val)
    21462121  TYPE(keys_type),  INTENT(IN)  :: ky(:)
    2147   lerr = SIZE(ky) == 0
    2148   IF(lerr) RETURN
    2149            val = fgetKeyIdx(strIdx(ky%name, tname), [keyn], ky, lerr)
    2150   IF(lerr) val = fgetKeyIdx(strIdx(ky%name, tnam ), [keyn], ky, lerr)
    2151 
     2122  CHARACTER(LEN=maxlen), ALLOCATABLE :: tname_all(:)
     2123  lerr = SIZE(ky) == 0;                 IF(lerr) RETURN
     2124  lerr = getKey('name', tname_all, ky); IF(lerr) RETURN
     2125           val = fgetKeyIdx(strIdx(tname_all, tname), [keyn], ky, lerr)
     2126  IF(lerr) val = fgetKeyIdx(strIdx(tname_all, tnam ), [keyn], ky, lerr)
    21522127END FUNCTION fgetKey
    21532128
     
    21662141  IF(lerr) RETURN
    21672142  val = str2int(sval)
    2168   lerr = val == -HUGE(1)
     2143  lerr = val == -HUGE(1) .AND. sval /= ''
    21692144  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(tname)//' is not'
    21702145  CALL msg(TRIM(s)//' an integer: '//TRIM(sval), modname, lerr)
     
    21832158  IF(lerr) RETURN
    21842159  val = str2real(sval)
    2185   lerr = val == -HUGE(1.)
     2160  lerr = val == -HUGE(1.) .AND. sval /= ''
    21862161  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(tname)//' is not'
    21872162  CALL msg(TRIM(s)//' a real: '//TRIM(sval), modname, lerr)
     
    22012176  IF(lerr) RETURN
    22022177  ival = str2bool(sval)
    2203   lerr = ival == -1
     2178  lerr = ival == -1 .AND. sval /= ''
    22042179  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(tname)//' is not'
    22052180  CALL msg(TRIM(s)//' a boolean: '//TRIM(sval), modname, lerr)
     
    22362211  IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN
    22372212  val = str2int(svals)
    2238   lerr = ANY(val == -HUGE(1))
     2213  lerr = ANY(val == -HUGE(1)) .AND. sval /= ''
    22392214  s = 'key "'//TRIM(keyn)//'" of '//TRIM(tname)//' is not'
    22402215  CALL msg(TRIM(s)//' an integer: '//TRIM(sval), modname, lerr)
     
    22562231  IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN
    22572232  val = str2real(svals)
    2258   lerr = ANY(val == -HUGE(1.))
     2233  lerr = ANY(val == -HUGE(1.)) .AND. sval /= ''
    22592234  s = 'key "'//TRIM(keyn)//'" of '//TRIM(tname)//' is not'
    22602235  CALL msg(TRIM(s)//' a real: '//TRIM(sval), modname, lerr)
     
    22772252  IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN
    22782253  ivals = str2bool(svals)
    2279   lerr = ANY(ivals == -1)
     2254  lerr = ANY(ivals == -1) .AND. sval /= ''
    22802255  s = 'key "'//TRIM(keyn)//'" of '//TRIM(tname)//' is not'
    22812256  CALL msg(TRIM(s)//' a boolean: '//TRIM(sval), modname, lerr)
     
    23122287  IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN
    23132288  val = str2int(svals)
    2314   lerr = ANY(val == -HUGE(1))
     2289  lerr = ANY(val == -HUGE(1)) .AND. sval /= ''
    23152290  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(tname)//' is not'
    23162291  CALL msg(TRIM(s)//' an integer: '//TRIM(sval), modname, lerr)
     
    23322307  IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN
    23332308  val = str2real(svals)
    2334   lerr = ANY(val == -HUGE(1.))
     2309  lerr = ANY(val == -HUGE(1.)) .AND. sval /= ''
    23352310  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(tname)//' is not'
    23362311  CALL msg(TRIM(s)//' a real: '//TRIM(sval), modname, lerr)
     
    23532328  IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN
    23542329  ivals = str2bool(svals)
    2355   lerr = ANY(ivals == -1)
     2330  lerr = ANY(ivals == -1) .AND. sval /= ''
    23562331  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(tname)//' is not'
    23572332  CALL msg(TRIM(s)//' a boolean: '//TRIM(sval), modname, lerr)
     
    24122387  lerr = .TRUE.
    24132388  IF(PRESENT(ky)) THEN;                 val = fgetKey(ky)                                !--- "ky"
    2414   ELSE IF(ALLOCATED(tracers)) THEN;     val = fgetKey(tracers(:)%keys)                   !--- "tracers"
     2389  ELSE IF(ALLOCATED(tracers)) THEN;     val = fgetKey(tracers(:))                        !--- "tracers"
    24152390     IF(lerr .AND. ASSOCIATED(isotope)) val = fgetKey(isotope%keys(:))                   !--- "isotope"
    24162391  END IF
     
    24272402  TYPE(keys_type),       INTENT(IN)  :: ky(:)
    24282403  LOGICAL,               ALLOCATABLE :: ler(:)
    2429   lerr = SIZE(ky) == 0; IF(lerr) RETURN
     2404  CHARACTER(LEN=maxlen), ALLOCATABLE :: tname_all(:)
     2405  lerr = SIZE(ky) == 0;                 IF(lerr) RETURN
     2406  lerr = getKey('name', tname_all, ky); IF(lerr) RETURN
    24302407  ALLOCATE(ler(SIZE(tname)))
    2431   val = [(fgetKeyIdx(strIdx(ky(:)%name, tname(iq)), keyn, ky, ler(iq)), iq = 1, SIZE(tname))]
     2408  val = [(fgetKeyIdx(strIdx(tname_all, tname(iq)), keyn, ky, ler(iq)), iq = 1, SIZE(tname))]
    24322409  lerr = ANY(ler)
    24332410END FUNCTION fgetKey
     
    24492426  IF(lerr) RETURN
    24502427  val = str2int(svals)
    2451   ll = val == -HUGE(1)
     2428  ll = val == -HUGE(1) .AND. (SIZE(svals) /=1 .OR. svals(1) /= '')
    24522429  lerr = ANY(ll); IF(.NOT.lerr) RETURN
    24532430  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(strStack(tname, MASK=ll))//' is not'
     
    24692446  IF(lerr) RETURN
    24702447  val = str2real(svals)
    2471   ll = val == -HUGE(1.)
     2448  ll = val == -HUGE(1.) .AND. (SIZE(svals) /=1 .OR. svals(1) /= '')
    24722449  lerr = ANY(ll); IF(.NOT.lerr) RETURN
    24732450  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(strStack(tname, MASK=ll))//' is not'
     
    24902467  IF(lerr) RETURN
    24912468  ivals = str2bool(svals)
    2492   ll = ivals == -1
     2469  ll = ivals == -1 .AND. (SIZE(svals) /=1 .OR. svals(1) /= '')
    24932470  lerr = ANY(ll); IF(.NOT.lerr) THEN; val = ivals == 1; RETURN; END IF
    24942471  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(strStack(tname, MASK=ll))//' is not'
     
    25022479!==============================================================================================================================
    25032480SUBROUTINE setKeysDBase(tracers_, isotopes_, isotope_)
    2504   TYPE(trac_type), OPTIONAL, INTENT(IN) ::  tracers_(:)
     2481  TYPE(keys_type), OPTIONAL, INTENT(IN) ::  tracers_(:)
    25052482  TYPE(isot_type), OPTIONAL, INTENT(IN) :: isotopes_(:)
    25062483  TYPE(isot_type), OPTIONAL, INTENT(IN) :: isotope_
     
    25112488  IF(PRESENT(isotopes_)) THEN; isotopes = isotopes_; ELSE; ALLOCATE(isotopes(0)); END IF
    25122489  IF(PRESENT(isotope_ )) THEN
    2513     ix = strIdx(isotopes(:)%parent, isotope_%parent)
     2490    ix = strIdx(isotopes(:)%name, isotope_%name)
    25142491    IF(ix /= 0) THEN
    25152492      isotopes(ix) = isotope_
     
    25222499!==============================================================================================================================
    25232500SUBROUTINE getKeysDBase(tracers_, isotopes_, isotope_)
    2524   TYPE(trac_type), OPTIONAL, ALLOCATABLE, INTENT(OUT) ::  tracers_(:)
     2501  TYPE(keys_type), OPTIONAL, ALLOCATABLE, INTENT(OUT) ::  tracers_(:)
    25252502  TYPE(isot_type), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: isotopes_(:)
    25262503  TYPE(isot_type), OPTIONAL,              INTENT(OUT) :: isotope_
     
    25292506  IF(PRESENT( tracers_)) THEN;  tracers_ =  tracers; ELSE; ALLOCATE( tracers_(0)); END IF
    25302507  IF(PRESENT(isotopes_)) THEN; isotopes_ = isotopes; ELSE; ALLOCATE(isotopes_(0)); END IF
    2531   IF(PRESENT(isotope_ )) THEN; ix = strIdx(isotopes(:)%parent, isotope%parent); IF(ix /= 0) isotope_=isotopes(ix); END IF
     2508  IF(PRESENT(isotope_ )) THEN; ix = strIdx(isotopes(:)%name, isotope%name); IF(ix /= 0) isotope_=isotopes(ix); END IF
    25322509END SUBROUTINE getKeysDBase
    25332510!==============================================================================================================================
     
    26052582  CHARACTER(LEN=*),             INTENT(IN)    :: tname
    26062583  TYPE(keys_type),              INTENT(IN)    ::  keys
    2607   TYPE(trac_type), ALLOCATABLE, INTENT(INOUT) :: tracs(:)
    2608   TYPE(trac_type), ALLOCATABLE :: tr(:)
     2584  TYPE(keys_type), ALLOCATABLE, INTENT(INOUT) :: tracs(:)
     2585  TYPE(keys_type), ALLOCATABLE :: tr(:)
    26092586  CHARACTER(LEN=maxlen), ALLOCATABLE :: tnames(:)
    26102587  INTEGER :: nt, ix
    26112588  IF(ALLOCATED(tracs)) THEN
    2612      lerr = getKey('name', tnames, ky=tracs(:)%keys); IF(lerr) RETURN
     2589     lerr = getKey('name', tnames, ky=tracs(:)); IF(lerr) RETURN
    26132590     nt = SIZE(tracs)
    26142591     ix = strIdx(tnames, tname)
     
    26222599     ix = 1; ALLOCATE(tracs(1))
    26232600  END IF
    2624   CALL addKey('name', tname, tracs(ix)%keys)
    2625   tracs(ix)%name = tname
    2626   tracs(ix)%keys = keys
     2601  CALL addKey('name', tname, tracs(ix))
     2602  tracs(ix) = keys
    26272603
    26282604END FUNCTION addTracer_1
     
    26392615LOGICAL FUNCTION delTracer_1(tname, tracs) RESULT(lerr)
    26402616  CHARACTER(LEN=*),                     INTENT(IN)    :: tname
    2641   TYPE(trac_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: tracs(:)
    2642   TYPE(trac_type), ALLOCATABLE :: tr(:)
     2617  TYPE(keys_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: tracs(:)
     2618  TYPE(keys_type), ALLOCATABLE :: tr(:)
    26432619  CHARACTER(LEN=maxlen), ALLOCATABLE :: tnames(:)
    26442620  INTEGER :: nt, ix
     
    26462622  IF(fmsg('Can''t remove tracer "'//TRIM(tname)//'" from an empty tracers descriptor', modname, lerr)) RETURN
    26472623  nt = SIZE(tracs)
    2648   lerr = getKey('name', tnames, ky=tracs(:)%keys); IF(lerr) RETURN
     2624  lerr = getKey('name', tnames, ky=tracs(:)); IF(lerr) RETURN
    26492625  ix = strIdx(tnames, tname)
    26502626  CALL msg('Removing tracer "'             //TRIM(tname)//'"', modname, ix /= 0)
     
    26902666
    26912667!==============================================================================================================================
    2692 !============ CONVERT WATER-DERIVED NAMES FROM FORMER TO CURRENT CONVENTION ; OTHER NAMES ARE LEFT UNTOUCHED ==================
    2693 !======= NAMES STRUCTURE: H2O[<phase>][_<isotope>][_<tag>] (<phase> from "old_phases", <isotope> from "oldH2OIso") ============
     2668!======== CONVERT WATER-DERIVED NAMES FROM FORMER TO CURRENT CONVENTION & VICE VERSA ; OTHER NAMES ARE LEFT UNTOUCHED =========
     2669!===== OLD NAMES STRUCTURE:  H2O[<phase>][_<isotope>][_<tag>] (<phase> from "old_phases",        <isotope> from "oldH2OIso") ==
     2670!====  NEW NAMES STRUCTURE: <var>[<phase_sep><phase>][_<tag>] (<phase> from "known_phases", <var>='H2O' or from "newH2OIso") ==
    26942671!==============================================================================================================================
    26952672CHARACTER(LEN=maxlen) FUNCTION old2newH2O_1(oldName, iPhase) RESULT(newName)
     
    27242701END FUNCTION old2newH2O_m
    27252702!==============================================================================================================================
    2726 
    2727 
    2728 !==============================================================================================================================
    2729 !============ CONVERT WATER-DERIVED NAMES FROM CURRENT TO FORMER CONVENTION ; OTHER NAMES ARE LEFT UNTOUCHED ==================
    2730 !==== NAMES STRUCTURE: <var>[<phase_sep><phase>][_<tag>] (<phase> from "known_phases", <var> = 'H2O' or from "newH2OIso") =====
    2731 !==============================================================================================================================
    27322703CHARACTER(LEN=maxlen) FUNCTION new2oldH2O_1(newName, iPhase) RESULT(oldName)
    27332704  CHARACTER(LEN=*),  INTENT(IN)  :: newName
Note: See TracChangeset for help on using the changeset viewer.