Changeset 5190 for LMDZ6/trunk/libf/misc


Ignore:
Timestamp:
Sep 15, 2024, 10:38:32 AM (5 months ago)
Author:
dcugnet
Message:

Revert to r5182 because r5183 still craches with gfortran for unclear reasons.
r5188 and r5189 have been included.

Location:
LMDZ6/trunk/libf/misc
Files:
1 deleted
1 edited

Legend:

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

    r5184 r5190  
    1010
    1111  PUBLIC :: maxlen                                              !--- PARAMETER FOR CASUAL STRING LENGTH
    12   PUBLIC :: keys_type, tracers, setGeneration, indexUpdate      !--- TRACERS  DESCRIPTION DATABASE + ASSOCIATED TOOLS
     12  PUBLIC :: trac_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                        !--- TOOLS TO SET/DEL/GET KEYS FROM/TO  tracers & isotopes
     16  PUBLIC :: addKey,    delKey,    getKey,    keys_type          !--- 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                                           !--- SAME AS iqIsoPha BUT ISOTOPES LIST STARTS WITH PARENT TRAC
     37  PUBLIC :: iqWIsoPha                                           !--- Idx IN qx(1:nqtot)     = f(isotope idx,   phase idx) but with normal water first
    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
    4344    CHARACTER(LEN=maxlen), ALLOCATABLE :: key(:)                !--- Keys string list
    4445    CHARACTER(LEN=maxlen), ALLOCATABLE :: val(:)                !--- Corresponding values string list
    4546  END TYPE keys_type
    4647!------------------------------------------------------------------------------------------------------------------------------
    47   TYPE :: isot_type                                             !=== TYPE FOR AN ISOTOPES FAMILY DESCENDING ON TRACER "name"
    48     CHARACTER(LEN=maxlen)              :: name                  !--- Isotopes family name (example: H2O)
     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)
    4973    TYPE(keys_type),       ALLOCATABLE :: keys(:)               !--- Isotopes keys/values pairs list     (length: niso)
    5074    LOGICAL                            :: check=.FALSE.         !--- Flag for checking routines triggering
     
    6488  TYPE :: dataBase_type                                         !=== TYPE FOR TRACERS SECTION
    6589    CHARACTER(LEN=maxlen) :: name                               !--- Section name
    66     TYPE(keys_type), ALLOCATABLE :: trac(:)                     !--- Tracers descriptors
     90    TYPE(trac_type), ALLOCATABLE :: trac(:)                     !--- Tracers descriptors
    6791  END TYPE dataBase_type
    6892!------------------------------------------------------------------------------------------------------------------------------
     
    115139
    116140  !=== TRACERS AND ISOTOPES DESCRIPTORS, USED BY getKey
    117   TYPE(keys_type), ALLOCATABLE, TARGET, SAVE ::  tracers(:)
     141  TYPE(trac_type), ALLOCATABLE, TARGET, SAVE ::  tracers(:)
    118142  TYPE(isot_type), ALLOCATABLE, TARGET, SAVE :: isotopes(:)
    119143
     
    169193!------------------------------------------------------------------------------------------------------------------------------
    170194  CHARACTER(LEN=*),                               INTENT(IN)  :: type_trac     !--- List of components used
    171   TYPE(keys_type), ALLOCATABLE, TARGET, OPTIONAL, INTENT(OUT) :: tracs(:)      !--- Tracers descriptor for external storage
     195  TYPE(trac_type), ALLOCATABLE, TARGET, OPTIONAL, INTENT(OUT) :: tracs(:)      !--- Tracers descriptor for external storage
    172196  LOGICAL,                              OPTIONAL, INTENT(IN)  :: lRepr         !--- Activate the HNO3 exceptions for REPROBUS
    173197  CHARACTER(LEN=maxlen),  ALLOCATABLE :: s(:), sections(:), trac_files(:)
    174   CHARACTER(LEN=maxlen) :: str, fname, tname, pname, cname, ttype
     198  CHARACTER(LEN=maxlen) :: str, fname, tname, pname, cname
    175199  INTEGER               :: nsec, ierr, it, ntrac, ns, ip, ix, fType
    176200  INTEGER, ALLOCATABLE  :: iGen(:)
     
    208232        CALL msg('This file is for air tracers only',           modname, ns == 3 .AND. it == 1)
    209233        CALL msg('This files specifies the transporting fluid', modname, ns == 4 .AND. it == 1)
    210         k => tracers(it)
     234        k => tracers(it)%keys
    211235
    212236        !=== NAME OF THE TRACER
     
    214238        ix = strIdx(oldHNO3, s(3))
    215239        IF(ix /= 0 .AND. lRep) tname = newHNO3(ix)                   !--- Exception for HNO3 (REPROBUS ONLY)
    216         CALL addKey('name', tname, tracers)                          !--- Set the name of the tracer
    217 !        tracers(it)%name = tname                                     !--- Copy tracers names in keys components
     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
    218243
    219244        !=== NAME OF THE COMPONENT
    220245        cname = type_trac                                            !--- Name of the model component
    221246        IF(ANY([(addPhase('H2O', ip), ip = 1, nphases)] == tname)) cname = 'lmdz'
    222         CALL addKey('component', cname, tracers)                     !--- Set the name of the model component
     247        tracers(it)%component = cname                                !--- Set component
     248        CALL addKey('component', cname, k)                           !--- Set the name of the model component
    223249
    224250        !=== NAME OF THE PARENT
     
    229255          IF(ix /= 0 .AND. lRep) pname = newHNO3(ix)                 !--- Exception for HNO3 (REPROBUS ONLY)
    230256        END IF
    231         CALL addKey('parent', pname, tracers)                        !--- Set the parent name
     257        tracers(it)%parent = pname                                   !--- Set the parent name
     258        CALL addKey('parent', pname, k)
    232259
    233260        !=== PHASE AND ADVECTION SCHEMES NUMBERS
    234         CALL addKey('phase', known_phases(ip:ip), tracers)           !--- Set the phase of the tracer (default: "g"azeous)
     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)
    235263        CALL addKey('hadv', s(1),  k)                                !--- Set the horizontal advection schemes number
    236264        CALL addKey('vadv', s(2),  k)                                !--- Set the vertical   advection schemes number
     
    238266      CLOSE(90)
    239267      lerr = setGeneration(tracers); IF(lerr) RETURN                 !--- Set iGeneration and gen0Name
    240       lerr = getKey('iGeneration', iGen, tracers(:))                 !--- Generation number
     268      lerr = getKey('iGeneration', iGen, tracers(:)%keys)            !--- Generation number
     269      WHERE(iGen == 2) tracers(:)%type = 'tag'                       !--- Set type:      'tracer' or 'tag'
    241270      DO it = 1, ntrac
    242         ttype = 'tracer'; IF(iGen(it) == 2) ttype = 'tag'
    243         CALL addKey('type', ttype, tracers(it))                 !--- Set the type of tracer
     271        CALL addKey('type', tracers(it)%type, tracers(it)%keys)      !--- Set the type of tracer
    244272      END DO
    245273      lerr = checkTracers(tracers, fname, fname); IF(lerr) RETURN    !--- Detect orphans and check phases
     
    263291  END IF
    264292  lerr = indexUpdate(tracers); IF(lerr) RETURN                       !--- Set iqParent, iqDescen, nqDescen, nqChildren
    265   IF(PRESENT(tracs)) tracs = tracers
     293  IF(PRESENT(tracs)) CALL MOVE_ALLOC(FROM=tracers, TO=tracs)
    266294END FUNCTION readTracersFiles
    267295!==============================================================================================================================
     
    311339! Purpose: Read the sections "snames(is)" (pipe-separated list) from each "fnames(is)"
    312340!   file and create the corresponding tracers set descriptors in the database "dBase":
    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
     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
    317345!------------------------------------------------------------------------------------------------------------------------------
    318346  CHARACTER(LEN=*), INTENT(IN)  :: fnames(:)                         !--- Files names
     
    367395  ndb= SIZE(dBase)                                                   !--- Current number of sections in the database
    368396  IF(PRESENT(defName)) THEN                                          !--- Add default values to all the tracers
    369     DO idb=n0,ndb                                                    !--- and remove the virtual tracer "defName"
    370        lerr = addDefault(dBase(idb)%trac, defName); IF(lerr) RETURN
    371     END DO
     397    DO idb=n0,ndb; CALL addDefault(dBase(idb)%trac, defName); END DO !--- and remove the virtual tracer "defName"
    372398  END IF
    373399  ll = strParse(snam, '|', keys = sec)                               !--- Requested sections names
     
    382408!------------------------------------------------------------------------------------------------------------------------------
    383409  CHARACTER(LEN=maxlen), ALLOCATABLE ::  s(:), v(:)
    384   TYPE(keys_type),       ALLOCATABLE :: tt(:)
     410  TYPE(trac_type),       ALLOCATABLE :: tt(:)
     411  TYPE(trac_type)       :: tmp
    385412  CHARACTER(LEN=1024)   :: str, str2
    386413  CHARACTER(LEN=maxlen) :: secn
     
    418445      tt = dBase(ndb)%trac(:)
    419446      v(1) = s(1); s(1) = 'name'                                     !--- Convert "name" into a regular key
    420       dBase(ndb)%trac = [tt(:), keys_type(s(:), v(:))]
    421       DEALLOCATE(tt)
     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)
    422450    END IF
    423451  END DO
     
    432460
    433461!==============================================================================================================================
    434 LOGICAL FUNCTION addDefault(t, defName) RESULT(lerr)
     462SUBROUTINE addDefault(t, defName)
    435463!------------------------------------------------------------------------------------------------------------------------------
    436464! Purpose: Add the keys from virtual tracer named "defName" (if any) and remove this virtual tracer.
    437465!------------------------------------------------------------------------------------------------------------------------------
    438   TYPE(keys_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: t(:)
     466  TYPE(trac_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: t(:)
    439467  CHARACTER(LEN=*),                     INTENT(IN)    :: defName
    440468  INTEGER :: jd, it, k
    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)
     469  TYPE(keys_type), POINTER :: ky
     470  TYPE(trac_type), ALLOCATABLE :: tt(:)
     471  jd = strIdx(t(:)%name, defName)
    445472  IF(jd == 0) RETURN
    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
     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
    449477  END DO
    450478  tt = [t(1:jd-1),t(jd+1:SIZE(t))]; CALL MOVE_ALLOC(FROM=tt, TO=t)   !--- Remove the virtual tracer named "defName"
    451 END FUNCTION addDefault
    452 !==============================================================================================================================
    453 
    454 !==============================================================================================================================
    455 LOGICAL FUNCTION subDefault(t, defName, lSubLocal) RESULT(lerr)
     479END SUBROUTINE addDefault
     480!==============================================================================================================================
     481
     482!==============================================================================================================================
     483SUBROUTINE subDefault(t, defName, lSubLocal)
    456484!------------------------------------------------------------------------------------------------------------------------------
    457485! Purpose: Substitute the keys from virtual tracer named "defName" (if any) and remove this virtual tracer.
    458486!          Substitute the keys locally (for the current tracer) if the flag "lSubLocal" is .TRUE.
    459487!------------------------------------------------------------------------------------------------------------------------------
    460   TYPE(keys_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: t(:)
     488  TYPE(trac_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: t(:)
    461489  CHARACTER(LEN=*),                     INTENT(IN)    :: defName
    462490  LOGICAL,                              INTENT(IN)    :: lSubLocal
    463491  INTEGER :: i0, it, ik
    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)
     492  TYPE(keys_type), POINTER     :: k0, ky
     493  TYPE(trac_type), ALLOCATABLE :: tt(:)
     494  i0 = strIdx(t(:)%name, defName)
    468495  IF(i0 == 0) RETURN
     496  k0 => t(i0)%keys
    469497  DO it = 1, SIZE(t); IF(it == i0) CYCLE                             !--- Loop on the tracers
     498    ky => t(it)%keys
    470499
    471500    !--- Substitute in the values of <key>=<val> pairs the keys defined in the virtual tracer "defName"
    472     DO ik = 1, SIZE(t(i0)%key); CALL strReplace(t(it)%val, t(i0)%key(ik), t(i0)%val(ik), .TRUE.); END DO
     501    DO ik = 1, SIZE(k0%key); CALL strReplace(ky%val, k0%key(ik), k0%val(ik), .TRUE.); END DO
    473502
    474503    IF(.NOT.lSubLocal) CYCLE
    475504    !--- Substitute in the values of <key>=<val> pairs the keys defined locally (in the current tracer)
    476     DO ik = 1, SIZE(t(it)%key); CALL strReplace(t(it)%val, t(it)%key(ik), t(it)%val(ik), .TRUE.); END DO
     505    DO ik = 1, SIZE(ky%key); CALL strReplace(ky%val, ky%key(ik), ky%val(ik), .TRUE.); END DO
    477506  END DO
    478507  tt = [t(1:i0-1),t(i0+1:SIZE(t))]; CALL MOVE_ALLOC(FROM=tt, TO=t)   !--- Remove the virtual tracer named "defName"
    479508
    480 END FUNCTION subDefault
     509END SUBROUTINE subDefault
    481510!==============================================================================================================================
    482511
     
    489518!        * Default values are provided for these keys because they are necessary.
    490519!------------------------------------------------------------------------------------------------------------------------------
    491   TYPE(keys_type), ALLOCATABLE, INTENT(INOUT) :: tr(:)                 !--- Tracer derived type vector
     520  TYPE(trac_type), ALLOCATABLE, INTENT(INOUT) :: tr(:)                 !--- Tracer derived type vector
    492521  CHARACTER(LEN=*),             INTENT(IN)    :: sname                 !--- Current section name
    493522  CHARACTER(LEN=*), OPTIONAL,   INTENT(IN)    :: fname                 !--- Tracers description file name
    494   TYPE(keys_type),       ALLOCATABLE :: ttr(:)
     523  TYPE(trac_type),       ALLOCATABLE :: ttr(:)
    495524  CHARACTER(LEN=maxlen), ALLOCATABLE :: ta(:), pa(:), tname(:), parent(:), dType(:)
    496525  CHARACTER(LEN=maxlen) :: msg1, modname
     
    500529  lerr = .FALSE.
    501530  nt = SIZE(tr)
    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
     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
    505534  nq = 0
    506535  !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     
    508537  !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    509538    !--- Extract useful keys: parent name, type, component name
    510     CALL addKey('component', sname,  tr(it))
     539    tr(it)%component = sname
     540    CALL addKey('component', sname,  tr(it)%keys)
    511541
    512542    !--- Determine the number of tracers and parents ; coherence checking
     
    535565    DO ipr = 1, npr                                                  !--- Loop on parents list elts
    536566      DO itr = 1, ntr                                                !--- Loop on tracers list elts
    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))
     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)
    543578        iq = iq + 1
    544579      END DO
     
    562597!          Check also for orphan tracers (tracers without parent).
    563598!------------------------------------------------------------------------------------------------------------------------------
    564   TYPE(keys_type),     INTENT(INOUT) :: tr(:)                        !--- Tracer derived type vector
     599  TYPE(trac_type),     INTENT(INOUT) :: tr(:)                        !--- Tracer derived type vector
    565600  INTEGER                            :: iq, jq, ig
    566601  CHARACTER(LEN=maxlen), ALLOCATABLE :: parent(:), tname(:)
     
    568603  CHARACTER(LEN=maxlen) :: modname
    569604  modname = 'setGeneration'
    570   lerr = getKey('name',   tname,  ky=tr(:)); IF(lerr) RETURN
    571   lerr = getKey('parent', parent, ky=tr(:)); IF(lerr) RETURN
     605  lerr = getKey('name',   tname,  ky=tr(:)%keys); IF(lerr) RETURN
     606  lerr = getKey('parent', parent, ky=tr(:)%keys); IF(lerr) RETURN
    572607  DO iq = 1, SIZE(tr)
    573608    jq = iq; ig = 0
     
    578613      ig = ig + 1
    579614    END DO
    580     CALL addKey('iGeneration',    ig,  tr(iq))
    581     CALL addKey('gen0Name', tname(jq), tr(iq))
     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)
    582619  END DO
    583620END FUNCTION setGeneration
     
    592629!   * check wether the phases are known or not (elements of "known_phases")
    593630!------------------------------------------------------------------------------------------------------------------------------
    594   TYPE(keys_type),            INTENT(IN) :: tr(:)                    !--- Tracers description vector
     631  TYPE(trac_type),            INTENT(IN) :: tr(:)                    !--- Tracer derived type vector
    595632  CHARACTER(LEN=*),           INTENT(IN) :: sname                    !--- Section name
    596633  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: fname                    !--- File name
     
    607644  mesg = 'Check section "'//TRIM(sname)//'"'
    608645  IF(PRESENT(fname)) mesg=TRIM(mesg)//' in file "'//TRIM(fname)//'"'
    609   lerr = getKey('iGeneration', iGen, tr(:));                    IF(lerr) RETURN
    610   lerr = getKey('name',       tname, tr(:));                    IF(lerr) RETURN
     646  lerr = getKey('iGeneration', iGen, tr(:)%keys);               IF(lerr) RETURN
     647  lerr = getKey('name',       tname, tr(:)%keys);               IF(lerr) RETURN
    611648
    612649  !=== CHECK FOR ORPHAN TRACERS
     
    615652  !=== CHECK PHASES
    616653  DO iq = 1, nq; IF(iGen(iq) /= 0) CYCLE                             !--- Generation O only is checked
    617     IF(getKey(['phases','phase '], pha, iq, tr(:), lDisp=.FALSE.)) pha = 'g'   !--- Phase
     654    IF(getKey(['phases','phase '], pha, iq, tr(:)%keys, lDisp=.FALSE.)) pha = 'g'   !--- Phase
    618655    np = LEN_TRIM(pha); bp(iq)=' '
    619656    DO ip = 1, np; p = pha(ip:ip); IF(INDEX(known_phases, p) == 0) bp(iq) = TRIM(bp(iq))//p; END DO
     
    630667! Purpose: Make sure that tracers are not repeated.
    631668!------------------------------------------------------------------------------------------------------------------------------
    632   TYPE(keys_type),            INTENT(IN) :: tr(:)                    !--- Tracers description vector
     669  TYPE(trac_type),            INTENT(IN) :: tr(:)                    !--- Tracer derived type vector
    633670  CHARACTER(LEN=*),           INTENT(IN) :: sname                    !--- Section name
    634671  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: fname                    !--- File name
     
    647684  nq=SIZE(tr,DIM=1); lerr=.FALSE.                                    !--- Number of lines ; error flag
    648685  tdup(:) = ''
    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
     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
    652689  DO iq = 1, nq
    653690    IF(dType(iq) == 'tag') CYCLE                                     !--- Tags can be repeated
     
    661698        DO k = 1, nq
    662699          IF(.NOT.ll(k)) CYCLE                                       !--- Skip tracers different from current one
    663           IF(getKey(['phases','phase '], phase, k, tr, lDisp=.FALSE.)) phase='g'!--- Get current phases
     700          IF(getKey(['phases','phase '], phase, k, tr%keys, lDisp=.FALSE.)) phase='g'!--- Get current phases
    664701          IF(INDEX(phase, p) /= 0) np = np + 1                       !--- One more appearance of current tracer with phase "p"
    665702        END DO
     
    681718! Purpose: Expand the phases in the tracers descriptor "tr". Phases are not repeated for a tracer, thanks to "checkUnique".
    682719!------------------------------------------------------------------------------------------------------------------------------
    683   TYPE(keys_type), ALLOCATABLE, INTENT(INOUT) :: tr(:)               !--- Tracers description vector
    684 !------------------------------------------------------------------------------------------------------------------------------
    685   TYPE(keys_type),       ALLOCATABLE :: ttr(:)
     720  TYPE(trac_type), ALLOCATABLE, INTENT(INOUT) :: tr(:)               !--- Tracer derived type vector
     721!------------------------------------------------------------------------------------------------------------------------------
     722  TYPE(trac_type),       ALLOCATABLE :: ttr(:)
    686723  INTEGER,               ALLOCATABLE ::  i0(:), iGen(:)
    687724  CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:), gen0N(:), phase(:), parents(:), dType(:)
     
    695732  nq = SIZE(tr, DIM=1)
    696733  nt = 0
    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')
     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')
    703740  DO iq = 1, nq                                                      !--- GET THE NUMBER OF TRACERS
    704741    IF(iGen(iq) /= 0) CYCLE                                          !--- Only deal with generation 0 tracers
     
    726763        IF(lTag) nam = TRIM(nam)//'_'//TRIM(tname(iq))               !--- <parent>_<name> for tags
    727764        ttr(it) = tr(iq)                                             !--- Same <key>=<val> pairs
    728         CALL addKey('name', nam, ttr(it))                            !--- Name with possibly phase suffix
    729         CALL addKey('phase', p,  ttr(it))                            !--- Single phase entry
     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)
    730770        IF(lExt) THEN
    731771          parent = parents(iq); IF(iGen(iq) > 0) parent = addPhase(parent, p)
    732772          gen0Nm =   gen0N(iq); IF(iGen(iq) > 0) gen0Nm = addPhase(gen0Nm, p)
    733           CALL addKey('parent',   parent, ttr(it))
    734           CALL addKey('gen0Name', gen0Nm, ttr(it))
     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)
    735777        END IF
    736778        it = it+1
     
    740782  END DO
    741783  CALL MOVE_ALLOC(FROM=ttr, TO=tr)
    742   CALL delKey(['phases'], tr)                                        !--- Remove "phases" key, useless since "phase" is defined
     784  CALL delKey(['phases'],tr)                                         !--- Remove few keys entries
    743785
    744786END FUNCTION expandPhases
     
    755797!   TO BE ADDED IF NECESSARY: HIGHER MOMENTS AT THE END
    756798!------------------------------------------------------------------------------------------------------------------------------
    757   TYPE(keys_type), INTENT(INOUT) :: tr(:)                            !--- Tracers description vector
    758 !------------------------------------------------------------------------------------------------------------------------------
    759   TYPE(keys_type),       ALLOCATABLE :: tr2(:)
    760   INTEGER,               ALLOCATABLE :: iy(:), iz(:), iGen(:)
     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(:)
    761804  CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:), gen0N(:)
    762805  INTEGER :: ig, ng, iq, jq, ip, nq, n, ix(SIZE(tr)), k
     
    764807!  tr2 is introduced in order to cope with a bug in gfortran 4.8.5 compiler
    765808!------------------------------------------------------------------------------------------------------------------------------
    766   lerr = getKey('iGeneration', iGen, tr); IF(lerr) RETURN            !--- Generation number
     809  lerr = getKey('iGeneration', iGen, tr%keys); IF(lerr) RETURN       !--- Generation number
    767810  nq = SIZE(tr)
    768811  DO ip = nphases, 1, -1
    769     lerr = getKey('name',     tname, tr); IF(lerr) RETURN            !--- Names of the tracers of first generation
     812    lerr = getKey('name',     tname, tr%keys); IF(lerr) RETURN       !--- Names of the tracers of first generation
    770813    iq = strIdx(tname, addPhase('H2O', ip))
    771814    IF(iq == 0) CYCLE
     
    783826    END DO
    784827  ELSE
    785     lerr = getKey('gen0Name', gen0N, tr); IF(lerr) RETURN            !--- Names of the tracers    iq = 1
     828    lerr = getKey('gen0Name',   gen0N, tr%keys); IF(lerr) RETURN     !--- Names of the tracers    iq = 1
    786829    DO jq = 1, nq                                                    !--- Loop on generation 0 tracers
    787830      IF(iGen(jq) /= 0) CYCLE                                        !--- Skip generations /= 0
     
    805848LOGICAL FUNCTION mergeTracers(sections, tr) RESULT(lerr)
    806849  TYPE(dataBase_type),  TARGET, INTENT(IN)  :: sections(:)
    807   TYPE(keys_type), ALLOCATABLE, INTENT(OUT) ::       tr(:)
    808   TYPE(keys_type), POINTER ::   t1(:),   t2(:)
     850  TYPE(trac_type), ALLOCATABLE, INTENT(OUT) ::       tr(:)
     851  TYPE(trac_type), POINTER ::   t1(:),   t2(:)
     852  TYPE(keys_type), POINTER ::   k1(:),   k2(:)
    809853  INTEGER,     ALLOCATABLE :: ixct(:), ixck(:)
    810854  INTEGER :: is, ik, ik1, ik2, nk2, i1, i2, nt2
     
    814858  lerr = .FALSE.
    815859  keys = ['parent     ', 'type       ', 'iGeneration']               !--- Mandatory keys
    816   t1 => sections(1)%trac(:)                                          !--- Alias: first tracers section
    817   lerr = getKey('name', n1, t1); IF(lerr) RETURN                     !--- Names of the tracers
     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
    818862  tr = t1
    819863  !----------------------------------------------------------------------------------------------------------------------------
     
    821865  !----------------------------------------------------------------------------------------------------------------------------
    822866    t2  => sections(is)%trac(:)                                      !--- Alias: current tracers section
    823     lerr = getKey('name', n2, t2); IF(lerr) RETURN                   !--- Names of the tracers
     867    k2  => t2(:)%keys
     868    lerr = getKey('name', n2, k2); IF(lerr) RETURN                   !--- Names of the tracers
    824869    nt2  = SIZE(t2(:), DIM=1)                                        !--- Number of tracers in section
    825870    ixct = strIdx(n1(:), n2(:))                                      !--- Indexes of common tracers
     
    829874    CALL msg(n1(PACK(ixct, MASK = ixct/=0)), modname, nmax=128)      !--- Display duplicates (the 128 first at most)
    830875    !--------------------------------------------------------------------------------------------------------------------------
    831     DO i2=1,nt2; tnam = TRIM(n2(i2))                                 !=== LOOP ON COMMON TRACERS
     876    DO i2=1,nt2; tnam = TRIM(t2(i2)%name)                            !=== LOOP ON COMMON TRACERS
    832877    !--------------------------------------------------------------------------------------------------------------------------
    833878      i1 = ixct(i2); IF(i1 == 0) CYCLE                               !--- Idx in t1(:) ; skip new tracers
     
    836881      s1=' of "'//TRIM(tnam)//'" in "'//TRIM(sections(is)%name)//'" not matching previous value'
    837882      DO ik = 1, SIZE(keys)
    838         lerr = getKey(keys(ik), v1, i1, t1)
    839         lerr = getKey(keys(ik), v2, i2, t2)
     883        lerr = getKey(keys(ik), v1, i1, k1)
     884        lerr = getKey(keys(ik), v2, i2, k2)
    840885        lerr = v1 /= v2; IF(fmsg(TRIM(keys(ik))//TRIM(s1), modname, lerr)) RETURN
    841886      END DO
    842887
    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)]
     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)]
    849894
    850895      !=== KEEP TRACK OF THE COMPONENTS NAMES: COMA-SEPARATED LIST
    851       lerr = getKey('component', v1, i1, t1)
    852       lerr = getKey('component', v2, i2, t2)
    853       CALL addKey('component', TRIM(v1)//','//TRIM(v2), tr(i1))
     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)
    854900
    855901      !=== FOR TRACERS COMMON TO PREVIOUS AND CURRENT SECTIONS: CHECK WETHER SOME KEYS HAVE DIFFERENT VALUES ; KEEP OLD ONE
    856902      DO ik2 = 1, nk2                                                !--- Collect the corresponding indices
    857903        ik1 = ixck(ik2); IF(ik1 == 0) CYCLE
    858         IF(t1(i1)%val(ik1) == t2(i2)%val(ik2)) ixck(ik2)=0
     904        IF(k1(i1)%val(ik1) == k2(i2)%val(ik2)) ixck(ik2)=0
    859905      END DO
    860906      IF(ALL(ixck==0)) CYCLE                                         !--- No identical keys with /=values => nothing to display
    861907      CALL msg('Key(s)'//TRIM(s1), modname)                          !--- Display the  keys with /=values (names list)
    862908      DO ik2 = 1, nk2                                                !--- Loop on keys found in both t1(:) and t2(:)
    863         knam = t2(i2)%key(ik2)                                       !--- Name of the current key
     909        knam = k2(i2)%key(ik2)                                       !--- Name of the current key
    864910        ik1 = ixck(ik2)                                              !--- Corresponding index in t1(:)
    865911        IF(ik1 == 0) CYCLE                                           !--- New keys are skipped
    866         v1 = t1(i1)%val(ik1); v2 = t2(i2)%val(ik2)                   !--- Key values in t1(:) and t2(:)
     912        v1 = k1(i1)%val(ik1); v2 = k2(i2)%val(ik2)                   !--- Key values in t1(:) and t2(:)
    867913        CALL msg(' * '//TRIM(knam)//'='//TRIM(v2)//' ; previous value kept:'//TRIM(v1), modname)
    868914      END DO
     
    879925LOGICAL FUNCTION cumulTracers(sections, tr, lRename) RESULT(lerr)
    880926  TYPE(dataBase_type),  TARGET, INTENT(IN)  :: sections(:)
    881   TYPE(keys_type), ALLOCATABLE, INTENT(OUT) ::       tr(:)
     927  TYPE(trac_type), ALLOCATABLE, INTENT(OUT) ::       tr(:)
    882928  LOGICAL,            OPTIONAL, INTENT(IN)  :: lRename               !--- .TRUE.: add a section suffix to identical names
    883929  CHARACTER(LEN=maxlen)  :: tnam_new, modname
     
    888934  tr = [( sections(is)%trac(:), is = 1, SIZE(sections) )]            !--- Concatenated tracers vector
    889935  IF(PRESENT(lRename)) THEN; IF(lRename) RETURN; END IF              !--- No renaming: finished
    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
     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
    893939  !----------------------------------------------------------------------------------------------------------------------------
    894940  DO iq = 1, SIZE(tr); IF(COUNT(tname == tname(iq)) == 1) CYCLE      !=== LOOP ON TRACERS
    895941  !----------------------------------------------------------------------------------------------------------------------------
    896942    tnam_new = TRIM(tname(iq))//'_'//TRIM(comp(iq))                  !--- Same with section extension
    897     CALL addKey('name', tnam_new, tr(iq))                            !--- Modify tracer name
     943    CALL addKey('name', tnam_new, tr(iq)%keys)                       !--- Modify tracer name
     944    tr(iq)%name = TRIM(tnam_new)                                     !--- Modify tracer name
    898945    !--------------------------------------------------------------------------------------------------------------------------
    899946    DO jq = 1, SIZE(tr); IF(parent(jq) /= tname(iq)) CYCLE           !=== LOOP ON TRACERS PARENTS
    900947    !--------------------------------------------------------------------------------------------------------------------------
    901       CALL addKey('parent', tnam_new, tr(jq))                        !--- Modify tracer name
     948      CALL addKey('parent', tnam_new, tr(jq)%keys)                   !--- Modify tracer name
     949      tr(jq)%parent = TRIM(tnam_new)                                 !--- Modify tracer name
    902950    !--------------------------------------------------------------------------------------------------------------------------
    903951    END DO
     
    946994    tmp = int2str([(iq, iq=1, nq)])
    947995  ELSE
    948     lerr = getKey(nam, tmp, dBase(idb)%trac(:), lDisp=lMandatory)
     996    lerr = getKey(nam, tmp, dBase(idb)%trac(:)%keys, lDisp=lMandatory)
    949997  END IF
    950998  IF(lerr) THEN; lerr = lMandatory; RETURN; END IF
     
    9651013LOGICAL FUNCTION aliasTracer(tname, trac, alias) RESULT(lerr)                  !=== TRACER NAMED "tname" - SCALAR
    9661014  CHARACTER(LEN=*),         INTENT(IN)  :: tname
    967   TYPE(keys_type), TARGET,  INTENT(IN)  :: trac(:)
    968   TYPE(keys_type), POINTER, INTENT(OUT) :: alias
     1015  TYPE(trac_type), TARGET,  INTENT(IN)  :: trac(:)
     1016  TYPE(trac_type), POINTER, INTENT(OUT) :: alias
    9691017  INTEGER :: it
    9701018  CHARACTER(LEN=maxlen), ALLOCATABLE :: tnames(:)
    9711019  alias => NULL()
    972   lerr = getKey('name', tnames, trac(:))
     1020  lerr = getKey('name', tnames, trac(:)%keys)
    9731021  it = strIdx(tnames, tname)
    9741022  lerr = it /= 0; IF(.NOT.lerr) alias => trac(it)
     
    9761024!==============================================================================================================================
    9771025LOGICAL FUNCTION trSubset_Indx(trac, idx, alias) RESULT(lerr)                  !=== TRACERS WITH INDICES "idx(:)" - VECTOR
    978   TYPE(keys_type), ALLOCATABLE, INTENT(IN)  ::  trac(:)
     1026  TYPE(trac_type), ALLOCATABLE, INTENT(IN)  ::  trac(:)
    9791027  INTEGER,                      INTENT(IN)  ::   idx(:)
    980   TYPE(keys_type), ALLOCATABLE, INTENT(OUT) :: alias(:)
     1028  TYPE(trac_type), ALLOCATABLE, INTENT(OUT) :: alias(:)
    9811029  alias = trac(idx)
    9821030  lerr = indexUpdate(alias)
     
    9841032!------------------------------------------------------------------------------------------------------------------------------
    9851033LOGICAL FUNCTION trSubset_Name(trac, tname, alias) RESULT(lerr)                !=== TRACERS NAMED "tname(:)" - VECTOR
    986   TYPE(keys_type), ALLOCATABLE, INTENT(IN)  ::  trac(:)
     1034  TYPE(trac_type), ALLOCATABLE, INTENT(IN)  ::  trac(:)
    9871035  CHARACTER(LEN=*),             INTENT(IN)  :: tname(:)
    988   TYPE(keys_type), ALLOCATABLE, INTENT(OUT) :: alias(:)
     1036  TYPE(trac_type), ALLOCATABLE, INTENT(OUT) :: alias(:)
    9891037  CHARACTER(LEN=maxlen), ALLOCATABLE :: tnames(:)
    990   lerr = getKey('name', tnames, trac(:))
     1038  lerr = getKey('name', tnames, trac(:)%keys)
    9911039  alias = trac(strIdx(tnames, tname))
    9921040  lerr = indexUpdate(alias)
     
    9941042!==============================================================================================================================
    9951043LOGICAL FUNCTION trSubset_gen0Name(trac, gen0Nm, alias) RESULT(lerr)           !=== TRACERS OF COMMON 1st GENERATION ANCESTOR
    996   TYPE(keys_type), ALLOCATABLE, INTENT(IN)  :: trac(:)
     1044  TYPE(trac_type), ALLOCATABLE, INTENT(IN)  :: trac(:)
    9971045  CHARACTER(LEN=*),             INTENT(IN)  :: gen0Nm
    998   TYPE(keys_type), ALLOCATABLE, INTENT(OUT) :: alias(:)
     1046  TYPE(trac_type), ALLOCATABLE, INTENT(OUT) :: alias(:)
    9991047  CHARACTER(LEN=maxlen), ALLOCATABLE :: gen0N(:)
    1000   lerr = getKey('gen0Name', gen0N, trac(:))
     1048  lerr = getKey('gen0Name', gen0N, trac(:)%keys)
    10011049  alias = trac(strFind(delPhase(gen0N), gen0Nm))
    10021050  lerr = indexUpdate(alias)
     
    10061054
    10071055!==============================================================================================================================
    1008 !=== UPDATE THE INDEXES iqParent, iqDescen, nqDescen, nqChildren IN THE TRACERS DESCRIPTOR LIST "tr" ==========================
     1056!=== UPDATE THE INDEXES iqParent, iqDescend AND iGeneration IN THE TRACERS DESCRIPTOR LIST "tr" (USEFULL FOR SUBSETS) =========
    10091057!==============================================================================================================================
    10101058LOGICAL FUNCTION indexUpdate(tr) RESULT(lerr)
    1011   TYPE(keys_type), INTENT(INOUT) :: tr(:)
     1059  TYPE(trac_type), INTENT(INOUT) :: tr(:)
    10121060  INTEGER :: iq, jq, nq, ig, nGen
    10131061  INTEGER,               ALLOCATABLE :: iqDescen(:), ix(:), iy(:)
    10141062  CHARACTER(LEN=maxlen), ALLOCATABLE :: tnames(:), parent(:)
    10151063  INTEGER,       DIMENSION(SIZE(tr)) :: iqParent, iGen
    1016   lerr = getKey('name',   tnames, tr); IF(lerr) RETURN               !--- Names
    1017   lerr = getKey('parent', parent, tr); IF(lerr) RETURN               !--- Parents
     1064  lerr = getKey('name',   tnames, tr%keys); IF(lerr) RETURN          !--- Names
     1065  lerr = getKey('parent', parent, tr%keys); IF(lerr) RETURN          !--- Parents
    10181066  nq = SIZE(tr)
    10191067
    1020   !=== iqParent
     1068  !=== iqParent, iGeneration
    10211069  DO iq = 1, nq; iGen(iq) = 0; jq = iq
    10221070    iqParent(iq) = strIdx(tnames, parent(iq))
    10231071    DO; jq = strIdx(tnames, parent(jq)); IF(jq == 0) EXIT; iGen(iq) = iGen(iq) + 1; END DO
    1024     CALL addKey('iqParent', iqParent(iq), tr(iq))
     1072    CALL addKey('iqParent',   parent(iq), tr(iq)%keys)
     1073    CALL addKey('iqGeneration', iGen(iq), tr(iq)%keys)
    10251074  END DO
    10261075
     
    10291078  DO iq = 1, nq
    10301079    ix = [iq]; ALLOCATE(iqDescen(0))
    1031     CALL addKey('nqChildren', 0, tr(iq))
    10321080    DO ig = iGen(iq)+1, nGen
    10331081      iy = find(iqParent, ix); iqDescen = [iqDescen, iy]; ix = iy
    10341082      IF(ig /= iGen(iq)+1) CYCLE
    1035       CALL addKey('nqChildren', SIZE(iqDescen), tr(iq))
     1083      CALL addKey('nqChildren', SIZE(iqDescen), tr(iq)%keys)
     1084      tr(iq)%nqChildren = SIZE(iqDescen)
    10361085    END DO
    1037     CALL addKey('iqDescen', strStack(int2str(iqDescen)), tr(iq))
    1038     CALL addKey('nqDescen',             SIZE(iqDescen),  tr(iq))
     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)
    10391090    DEALLOCATE(iqDescen)
    10401091  END DO
     
    10441095 
    10451096!==============================================================================================================================
    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"    ====
     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"  ====
    10481099!===  * For each isotopes class, the <key>=<val> vector of each tracer is moved into the isotopes descriptor "isot"        ====
    10491100!=== NOTES:                                                                                                                ====
    10501101!===  * Most of the "isot" components have been defined in the calling routine (processIsotopes):                          ====
    1051 !===      name,  nzone, zone(:),  niso, keys(:)%name,  ntiso, trac(:),  nphas, phas,  iqIsoPha(:,:),  itZonPhi(:,:)        ====
     1102!===      parent,  nzone, zone(:),  niso, keys(:)%name,  ntiso, trac(:),  nphas, phas,  iqIsoPha(:,:),  itZonPhi(:,:)      ====
    10521103!===  * Same syntax for isotopes file and "tracer.def": a tracers section contains one line for each of its isotopes       ====
    10531104!===  * Each tracers section can contain a "params" virtual isotope line of isotopes parameters default values             ====
     
    10581109LOGICAL FUNCTION readIsotopesFile(fnam, isot) RESULT(lerr)
    10591110  CHARACTER(LEN=*),        INTENT(IN)    :: fnam                     !--- Input file name
    1060   TYPE(isot_type), TARGET, INTENT(INOUT) :: isot(:)                  !--- Isotopes descriptors (field %name must be defined!)
     1111  TYPE(isot_type), TARGET, INTENT(INOUT) :: isot(:)                  !--- Isotopes descriptors (field %parent must be defined!)
    10611112  LOGICAL :: lFound
    10621113  INTEGER :: is, iis, it, idb, ndb, nb0
    1063   CHARACTER(LEN=maxlen), ALLOCATABLE :: vals(:), tname(:), iname(:)
     1114  CHARACTER(LEN=maxlen), ALLOCATABLE :: vals(:)
    10641115  CHARACTER(LEN=maxlen)              :: modname
    1065   TYPE(keys_type),           POINTER ::  t
     1116  TYPE(trac_type),           POINTER ::   tt(:), t
    10661117  TYPE(dataBase_type),   ALLOCATABLE ::  tdb(:)
    10671118  modname = 'readIsotopesFile'
    10681119
    10691120  !--- THE INPUT FILE MUST BE PRESENT
    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)
     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
    10761125  nb0 = SIZE(dBase, DIM=1)+1                                         !--- Next database element index
    1077   lerr = readSections(fnam,strStack(isot(:)%name,'|')); IF(lerr) RETURN !--- Read sections, one each isotopes class %name
     1126  lerr = readSections(fnam,strStack(isot(:)%parent,'|')); IF(lerr) RETURN !--- Read sections, one each parent tracer
    10781127  ndb = SIZE(dBase, DIM=1)                                           !--- Current database size
    10791128  DO idb = nb0, ndb
     
    10811130
    10821131    !--- GET FEW GLOBAL KEYS FROM "def" FILES AND ADD THEM TO THE 'params' SECTION
    1083 !    lerr = addKeysFromDef(dBase(idb)%trac, 'params');     IF(lerr) RETURN
     1132    CALL addKeysFromDef(dBase(idb)%trac, 'params')
    10841133
    10851134    !--- SUBSTITUTE THE KEYS DEFINED IN THE 'params' VIRTUAL TRACER ; SUBSTITUTE LOCAL KEYS ; REMOVE 'params' VIRTUAL TRACER
    1086     lerr = subDefault(dBase(idb)%trac, 'params', .TRUE.); IF(lerr) RETURN
     1135    CALL subDefault(dBase(idb)%trac, 'params', .TRUE.)
     1136
     1137    tt => dBase(idb)%trac
    10871138
    10881139    !--- 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
    10911140    DO it = 1, SIZE(dBase(idb)%trac)
    10921141      t => dBase(idb)%trac(it)
    1093       is = strIdx(iname, tname(it))                                  !--- Index in "iname(:)" of isotope "tname(it)"
     1142      is = strIdx(isot(iis)%keys(:)%name, t%name)                    !--- Index in "isot(iis)%keys(:)%name" of isotope "t%name"
    10941143      IF(is == 0) CYCLE
    1095       lerr = ANY(reduceExpr(t%val, vals)); IF(lerr) RETURN           !--- Reduce expressions ; detect non-numerical elements
    1096       isot(iis)%keys(is)%key = t%key
     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
    10971146      isot(iis)%keys(is)%val = vals
    10981147    END DO
    10991148
    11001149    !--- CHECK FOR MISSING ISOTOPES (NO KEYS ALLOCATED)
    1101     lerr = checkList(iname, .NOT.[( ALLOCATED(isot(iis)%keys(is)%key), is=1, SIZE(isot(iis)%keys) )], &
     1150    lerr = checkList(isot(iis)%keys(:)%name, .NOT.[( ALLOCATED(isot(iis)%keys(is)%key), is=1, SIZE(isot(iis)%keys) )], &
    11021151                     'Check file "'//TRIM(fnam)//'" in section "'//TRIM(dBase(idb)%name)//'"', 'isotopes', 'missing')
    11031152    IF(lerr) RETURN
     
    11121161
    11131162  !--- GET THE isoCheck ENTRY FROM THE *.DEF FILES (MIGHT BE CHANGED TO A CLASS-DEPENDANT KEYWORD)
    1114   CALL get_in('ok_iso_verif', isot(strIdx(iname, 'H2O'))%check, .FALSE.)
     1163  CALL get_in('ok_iso_verif', isot(strIdx(isot%parent, 'H2O'))%check, .FALSE.)
    11151164
    11161165  lerr = dispIsotopes()
     
    11221171  INTEGER :: ik, nk, ip, it, nt
    11231172  CHARACTER(LEN=maxlen) :: prf
    1124   CHARACTER(LEN=maxlen), ALLOCATABLE :: ttl(:), val(:,:), tname(:)
     1173  CHARACTER(LEN=maxlen), ALLOCATABLE :: ttl(:), val(:,:)
    11251174  CALL msg('Isotopes parameters read from file "'//TRIM(fnam)//'":', modname)
    1126   DO ip = 1, SIZE(isot)                                              !--- Loop on isotopes classes
    1127     IF(SIZE(isot(ip)%keys) == 0) CYCLE
     1175  DO ip = 1, SIZE(isot)                                              !--- Loop on parents tracers
    11281176    nk = SIZE(isot(ip)%keys(1)%key)                                  !--- Same keys for each isotope
    11291177    nt = SIZE(isot(ip)%keys)                                         !--- Number of isotopes
     
    11311179    ALLOCATE(ttl(nk+2), val(nt,nk+1))
    11321180    ttl(1:2) = ['it  ','name']; ttl(3:nk+2) = isot(ip)%keys(1)%key(:)!--- Titles line with keys names
    1133     lerr = getKey('name', tname, isot(ip)%keys); IF(lerr) RETURN
    1134     val(:,1) = tname                                                 !--- Values table 1st column: isotopes names
     1181    val(:,1) = isot(ip)%keys(:)%name                                 !--- Values table 1st column: isotopes names 
    11351182    DO ik = 1, nk
    11361183      DO it = 1, nt
     
    11521199!=== IF ISOTOPES (2ND GENERATION TRACERS) ARE DETECTED:                                                                     ===
    11531200!===    * COMPUTE MOST OF THE RELATED QUANTITIES ("isot" COMPONENTS).                                                       ===
    1154 !===    * COMPUTE FEW ISOTOPES-DEDICATED "trac" COMPONENTS (defined by "keys(:)")                                           ===
    1155 !===    * CALL readIsotopesFile TO GET PHYSICAL QUANTITIES (<key>=<val> PAIRS)     /!\ DISABLED FUNCTION /!\                ===
    1156 !==============================================================================================================================
    1157 LOGICAL 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 :: 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(:)
     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!==============================================================================================================================
     1205LOGICAL 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
    11701216
    11711217  lerr = .FALSE.
    11721218  modname = 'readIsotopesFile'
    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
     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
    11881228
    11891229  !--- GET FROM "tracers" THE FULL LIST OF AVAILABLE ISOTOPES CLASSES
    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
     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
    11981238    END DO
    1199     iCla = iClasses
     1239    p = iNames; nbIso = SIZE(p)
    12001240  END IF
    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
     1241  IF(ALLOCATED(isotopes)) DEALLOCATE(isotopes)
     1242  ALLOCATE(isotopes(nbIso))
     1243
    12101244  IF(nbIso==0) RETURN                                                !=== NO ISOTOPES: FINISHED
    12111245
    12121246  !--- ISOTOPES RELATED VARIABLES ; NULL OR EMPTY IF NO ISOTOPES
    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")
     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")
    12331266    !    NOTE: One might like to create a similar variable for 2nd generation tagging tracers (tagging the gen1 tracers)
    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
     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
    12451278
    12461279    !=== Tables giving the index in a table of effectively found items for each dynamical tracer (1<=iq<=nqtot)
    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
     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
    12571288    END DO
    12581289
    12591290    !=== Table used to get iq (index in dyn array, size nqtot) from the isotope and phase indexes ; the full isotopes list
    12601291    !    (including tagging tracers) is sorted this way:  iso1, iso2, ..., iso1_zone1, iso2_zone1, ..., iso1_zoneN, iso2_zoneN
    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] )
     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] )
    12631294    !=== Table used to get iq (index in dyn array, size nqtot) from the water and isotope and phase indexes ; the full isotopes list
    12641295    !    (including tagging tracers) is sorted this way:  iso1, iso2, ..., iso1_zone1, iso2_zone1, ..., iso1_zoneN, iso2_zoneN
    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] )
     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] )
    12671298    !=== Table used to get ix (index in tagging tracers isotopes list, size ntiso) from the zone and isotope indexes
    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] )
     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] )
    12701301  END DO
    12711302
    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
     1303  !=== READ PHYSICAL PARAMETERS FROM isoFile FILE
     1304!  lerr = readIsotopesFile(isoFile, isotopes); IF(lerr) RETURN! on commente pour ne pas chercher isotopes_params.def
    12761305
    12771306  !--- GET THE isoCheck ENTRY FROM THE *.DEF FILES (MIGHT BE CHANGED TO A CLASS-DEPENDANT KEYWORD)
     
    12821311
    12831312  !=== SELECT WATER ISOTOPES CLASS OR, IF UNFOUND, THE FIRST ISOTOPES CLASS
    1284   IF(isoSelect('H2O', lVerbose=.TRUE.)) THEN
    1285     iH2O = ixIso
    1286   ELSE
    1287     lerr = isoSelect(1, lVerbose=.TRUE.)
    1288   END IF
     1313  IF(isoSelect('H2O', .TRUE.)) THEN; iH2O = ixIso; ELSE; lerr = isoSelect(1, .TRUE.); END IF
    12891314
    12901315CONTAINS
     
    12941319!------------------------------------------------------------------------------------------------------------------------------
    12951320  INTEGER :: ix, it, ip, np, iz, nz, npha, nzon
     1321  TYPE(isot_type), POINTER :: i
    12961322  DO ix = 1, nbIso
    1297     IF(     PRESENT(isot)) i1 => isot    (ix)
    1298     IF(.NOT.PRESENT(isot)) i1 => isotopes(ix)
     1323    i => isotopes(ix)
    12991324    !--- Check whether each isotope and tagging isotopic tracer is present in the same number of phases
    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)])
     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)])
    13021327      lerr = np /= npha
    1303       CALL msg(TRIM(int2str(np))//       ' phases instead of '//TRIM(int2str(npha))//' for '//TRIM(i1%trac(it)), modname, lerr)
     1328      CALL msg(TRIM(int2str(np))//' phases instead of '//TRIM(int2str(npha))//' for '//TRIM(i%trac(it)), modname, lerr)
    13041329      IF(lerr) RETURN
    13051330    END DO
    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)])
     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)])
    13081333      lerr = nz /= nzon
    1309       CALL msg(TRIM(int2str(nz))//' tagging zones instead of '//TRIM(int2str(nzon))//' for '//TRIM(i1%trac(it)), modname, lerr)
     1334      CALL msg(TRIM(int2str(nz))//' tagging zones instead of '//TRIM(int2str(nzon))//' for '//TRIM(i%trac(it)), modname, lerr)
    13101335      IF(lerr) RETURN
    13111336    END DO
     
    13201345!==============================================================================================================================
    13211346!=== THE ROUTINE isoSelect IS USED TO SWITCH FROM AN ISOTOPE FAMILY TO ANOTHER: ISOTOPES DEPENDENT PARAMETERS ARE UPDATED
    1322 !     Single generic "isoSelect" routine, using the predefined index of the class (fast version) or its name (first call).
    1323 !==============================================================================================================================
    1324 LOGICAL FUNCTION isoSelectByName(iClass, isot, lVerbose) RESULT(lerr)
     1347!     Single generic "isoSelect" routine, using the predefined index of the parent (fast version) or its name (first call).
     1348!==============================================================================================================================
     1349LOGICAL FUNCTION isoSelectByName(iName, lVerbose) RESULT(lerr)
    13251350   IMPLICIT NONE
    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(:)
     1351   CHARACTER(LEN=*),  INTENT(IN) :: iName
     1352   LOGICAL, OPTIONAL, INTENT(IN) :: lVerbose
    13301353   INTEGER :: iIso
    13311354   LOGICAL :: lV
    1332    lV = .FALSE.;    IF(PRESENT(lVerbose)) lV = lVerbose
    1333    iso => isotopes; IF(PRESENT(isot))    iso => isot
    1334    iIso = strIdx(iso(:)%name, iClass)
     1355   lV = .FALSE.; IF(PRESENT(lVerbose)) lV = lVerbose
     1356   iIso = strIdx(isotopes(:)%parent, iName)
    13351357   lerr = iIso == 0
    13361358   IF(lerr) THEN
    13371359      niso = 0; ntiso = 0; nzone = 0; nphas = 0; isoCheck=.FALSE.
    1338       CALL msg('no isotope family named "'//TRIM(iClass)//'"', ll=lV)
     1360      CALL msg('no isotope family named "'//TRIM(iName)//'"', ll=lV)
    13391361      RETURN
    13401362   END IF
    1341    lerr = isoSelectByIndex(iIso, iso, lV)
     1363   lerr = isoSelectByIndex(iIso, lV)
    13421364END FUNCTION isoSelectByName
    13431365!==============================================================================================================================
    1344 LOGICAL FUNCTION isoSelectByIndex(iIso, isot, lVerbose) RESULT(lerr)
     1366LOGICAL FUNCTION isoSelectByIndex(iIso, lVerbose) RESULT(lerr)
    13451367   IMPLICIT NONE
    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(:)
     1368   INTEGER,           INTENT(IN) :: iIso
     1369   LOGICAL, OPTIONAL, INTENT(IN) :: lVerbose
    13501370   LOGICAL :: lV
    1351    lV = .FALSE.;  IF(PRESENT(lVerbose)) lV = lVerbose
    1352    i => isotopes; IF(PRESENT(isot))      i => isot
     1371   lv = .FALSE.; IF(PRESENT(lVerbose)) lv = lVerbose
    13531372   lerr = .FALSE.
    13541373   IF(iIso == ixIso) RETURN                                          !--- Nothing to do if the index is already OK
    1355    lerr = iIso<=0 .OR. iIso>SIZE(i)
     1374   lerr = iIso<=0 .OR. iIso>SIZE(isotopes)
    13561375   CALL msg('Inconsistent isotopes family index '//TRIM(int2str(iIso))//': should be > 0 and <= '&
    1357           //TRIM(int2str(SIZE(i)))//'"', ll = lerr .AND. lV)
     1376          //TRIM(int2str(SIZE(isotopes)))//'"', ll = lerr .AND. lV)
    13581377   IF(lerr) RETURN
    13591378   ixIso = iIso                                                      !--- Update currently selected family index
    1360    isotope  => i(ixIso)                                              !--- Select corresponding component
     1379   isotope  => isotopes(ixIso)                                       !--- Select corresponding component
    13611380   isoKeys  => isotope%keys;     niso     = isotope%niso
    13621381   isoName  => isotope%trac;     ntiso    = isotope%ntiso
     
    13651384   itZonIso => isotope%itZonIso; isoCheck = isotope%check
    13661385   iqIsoPha => isotope%iqIsoPha
    1367    iqWIsoPha=> isotope%iqWIsoPha
     1386   iqWIsoPha => isotope%iqWIsoPha
    13681387END FUNCTION isoSelectByIndex
    13691388!==============================================================================================================================
     
    15091528!=== OVERWRITE THE KEYS OF THE TRACER NAMED "tr0" WITH THE VALUES FOUND IN THE *.def FILES, IF ANY. ===========================
    15101529!==============================================================================================================================
    1511 LOGICAL FUNCTION addKeysFromDef(t, tr0) RESULT(lerr)
    1512   TYPE(keys_type), ALLOCATABLE, INTENT(INOUT) :: t(:)
     1530SUBROUTINE addKeysFromDef(t, tr0)
     1531  TYPE(trac_type), ALLOCATABLE, INTENT(INOUT) :: t(:)
    15131532  CHARACTER(LEN=*),             INTENT(IN)    :: tr0
    15141533!------------------------------------------------------------------------------------------------------------------------------
    1515   CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:)
    15161534  CHARACTER(LEN=maxlen) :: val
    15171535  INTEGER               :: ik, jd
    1518   lerr = getKey('name', tname, t); IF(lerr) RETURN
    1519   jd = strIdx(tname(:), tr0)
     1536  jd = strIdx(t%name, tr0)
    15201537  IF(jd == 0) RETURN
    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.)
     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.)
    15241541  END DO
    1525 END FUNCTION addKeysFromDef
     1542END SUBROUTINE addKeysFromDef
    15261543!==============================================================================================================================
    15271544
     
    15331550  INTEGER,          INTENT(IN)    :: itr
    15341551  CHARACTER(LEN=*), INTENT(IN)    :: keyn(:)
    1535   TYPE(keys_type),  INTENT(INOUT) :: ky(:)
     1552  TYPE(trac_type),  INTENT(INOUT) :: ky(:)
    15361553!------------------------------------------------------------------------------------------------------------------------------
    15371554  CHARACTER(LEN=maxlen), ALLOCATABLE :: k(:), v(:)
     
    15391556  INTEGER :: iky
    15401557  IF(itr<=0 .OR. itr>SIZE(ky, DIM=1)) RETURN                          !--- Index is out of range
    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)
     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)
    15441561END SUBROUTINE delKey_1
    15451562!==============================================================================================================================
    15461563SUBROUTINE delKey(keyn, ky)
    15471564  CHARACTER(LEN=*), INTENT(IN)    :: keyn(:)
    1548   TYPE(keys_type),  INTENT(INOUT) :: ky(:)
     1565  TYPE(trac_type),  INTENT(INOUT) :: ky(:)
    15491566!------------------------------------------------------------------------------------------------------------------------------
    15501567  INTEGER :: iky
     
    15941611!=== TRY TO GET THE KEY NAMED "key" FOR THE "itr"th TRACER IN:                                                              ===
    15951612!===  * ARGUMENT "ky" DATABASE IF SPECIFIED ; OTHERWISE:                                                                    ===
    1596 !===  * IN INTERNAL TRACERS DATABASE "tracers(:)" (IF UNFOUND, IN INTERNAL ISOTOPES DATABASE "isotope%keys(:)")             ===
     1613!===  * IN INTERNAL TRACERS DATABASE "tracers(:)%keys" (IF UNFOUND, IN INTERNAL ISOTOPES DATABASE "isotope%keys(:)")        ===
    15971614!=== THE RETURNED VALUE (STRING, AN INTEGER, A REAL OR A LOGICAL) CAN BE EITHER:                                            ===
    15981615!===  * A SCALAR                                                                                                            ===
     
    16601677  lerr = .TRUE.
    16611678  IF(lerr .AND. PRESENT(ky))         val = fgetKey(ky)                                   !--- "ky"
    1662   IF(lerr .AND. ALLOCATED (tracers)) val = fgetKey(tracers(:))                           !--- "tracers"
     1679  IF(lerr .AND. ALLOCATED (tracers)) val = fgetKey(tracers(:)%keys)                      !--- "tracers"
    16631680  IF(lerr .AND. ASSOCIATED(isotope)) val = fgetKey(isotope%keys(:))                      !--- "isotope"
    16641681  IF(lerr .AND. PRESENT(def)) THEN
     
    17651782  IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN
    17661783  val = str2int(svals)
    1767   lerr = ANY(val == -HUGE(1)) .AND. sval /= ''
     1784  lerr = ANY(val == -HUGE(1))
    17681785  s = 'key "'//TRIM(keyn)//'" of tracer nr. '//TRIM(int2str(itr))//' is not'
    17691786  CALL msg(TRIM(s)//' an integer: '//TRIM(sval), modname, lerr)
     
    17851802  IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN
    17861803  val = str2real(svals)
    1787   lerr = ANY(val == -HUGE(1.)) .AND. sval /= ''
     1804  lerr = ANY(val == -HUGE(1.))
    17881805  s = 'key "'//TRIM(keyn)//'" of tracer nr. '//TRIM(int2str(itr))//' is not'
    17891806  CALL msg(TRIM(s)//' a real: '//TRIM(sval), modname, lerr)
     
    18061823  IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN
    18071824  ivals = str2bool(svals)
    1808   lerr = ANY(ivals == -1) .AND. sval /= ''
     1825  lerr = ANY(ivals == -1)
    18091826  s = 'key "'//TRIM(keyn)//'" of tracer nr. '//TRIM(int2str(itr))//' is not'
    18101827  CALL msg(TRIM(s)//' a boolean: '//TRIM(sval), modname, lerr)
     
    18431860  IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN
    18441861  val = str2int(svals)
    1845   lerr = ANY(val == -HUGE(1)) .AND. sval /= ''
     1862  lerr = ANY(val == -HUGE(1))
    18461863  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of tracer nr. '//TRIM(int2str(itr))//' is not'
    18471864  CALL msg(TRIM(s)//' an integer: '//TRIM(sval), modname, lerr)
     
    18641881  IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN
    18651882  val = str2real(svals)
    1866   lerr = ANY(val == -HUGE(1.)) .AND. sval /= ''
     1883  lerr = ANY(val == -HUGE(1.))
    18671884  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of tracer nr. '//TRIM(int2str(itr))//' is not'
    18681885  CALL msg(TRIM(s)//' a real: '//TRIM(sval), modname, lerr)
     
    18861903  IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN
    18871904  ivals = str2bool(svals)
    1888   lerr = ANY(ivals == -1) .AND. sval /= ''
     1905  lerr = ANY(ivals == -1)
    18891906  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of tracer nr. '//TRIM(int2str(itr))//' is not'
    18901907  CALL msg(TRIM(s)//' a boolean: '//TRIM(sval), modname, lerr)
     
    18931910!==============================================================================================================================
    18941911!==============================================================================================================================
    1895 LOGICAL 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)
     1912LOGICAL 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)
    19021920END FUNCTION getKeyByIndex_s1mm
    19031921!==============================================================================================================================
    1904 LOGICAL 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)
     1922LOGICAL 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)
    19111930END FUNCTION getKeyByIndex_i1mm
    19121931!==============================================================================================================================
    1913 LOGICAL 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)
     1932LOGICAL 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)
    19201940END FUNCTION getKeyByIndex_r1mm
    19211941!==============================================================================================================================
    1922 LOGICAL 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)
     1942LOGICAL 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)
    19291950END FUNCTION getKeyByIndex_l1mm
    19301951!==============================================================================================================================
    19311952!==============================================================================================================================
    1932 LOGICAL 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
     1953LOGICAL 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
    19381960!------------------------------------------------------------------------------------------------------------------------------
    19391961  CHARACTER(LEN=maxlen) :: s
     1962  CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:)
    19401963  INTEGER :: iq, nq(3), k
    19411964  LOGICAL :: lD, l(3)
     
    19441967  lerr = .TRUE.
    19451968  IF(PRESENT(ky)) THEN;                 val = fgetKey(ky)                                !--- "ky"
    1946   ELSE IF(ALLOCATED(tracers)) THEN;     val = fgetKey(tracers(:))                        !--- "tracers"
     1969  ELSE IF(ALLOCATED(tracers)) THEN;     val = fgetKey(tracers(:)%keys)                   !--- "tracers"
    19471970     IF(lerr .AND. ASSOCIATED(isotope)) val = fgetKey(isotope%keys(:))                   !--- "isotope"
    19481971  END IF
    1949   IF(.NOT.lerr) RETURN
     1972  IF(.NOT.lerr) THEN; IF(PRESENT(nam)) nam = tname; RETURN; END IF
    19501973  IF(.NOT.PRESENT(def)) THEN; CALL msg('No '//TRIM(s)//' found', modname, lD); RETURN; END IF
    19511974
     
    19681991  INTEGER :: iq
    19691992  lerr = SIZE(ky) == 0; IF(lerr) RETURN
     1993  tname = ky%name
    19701994  val = [(fgetKeyIdx(iq, keyn(:), ky, ler(iq)), iq = 1, SIZE(ky))]
    19711995  lerr = ANY(ler)
     
    19741998END FUNCTION getKeyByIndex_smmm
    19751999!==============================================================================================================================
    1976 LOGICAL 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
     2000LOGICAL 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
    19822007!------------------------------------------------------------------------------------------------------------------------------
    19832008  CHARACTER(LEN=maxlen) :: s
    19842009  CHARACTER(LEN=maxlen), ALLOCATABLE :: svals(:), tname(:)
    19852010  LOGICAL,               ALLOCATABLE ::    ll(:)
    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)
     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)
    19882013  IF(lerr) RETURN
    19892014  val = str2int(svals)
    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
     2015  ll = val == -HUGE(1)
     2016  lerr = ANY(ll); IF(.NOT.lerr) THEN; IF(PRESENT(nam)) nam = tname; RETURN; END IF
    19932017  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(strStack(PACK(tname, MASK=ll)))//' is not'
    19942018  CALL msg(TRIM(s)//' an integer: '//TRIM(strStack(svals, MASK=ll)), modname, lerr)
     2019  IF(.NOT.lerr .AND. PRESENT(nam)) nam = tname
    19952020END FUNCTION getKeyByIndex_immm
    19962021!==============================================================================================================================
    1997 LOGICAL 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
     2022LOGICAL 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
    20032029!------------------------------------------------------------------------------------------------------------------------------
    20042030  CHARACTER(LEN=maxlen) :: s
    20052031  CHARACTER(LEN=maxlen), ALLOCATABLE :: svals(:), tname(:)
    20062032  LOGICAL,               ALLOCATABLE ::    ll(:)
    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)
     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)
    20092035  IF(lerr) RETURN
    20102036  val = str2real(svals)
    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
     2037  ll = val == -HUGE(1.)
     2038  lerr = ANY(ll); IF(.NOT.lerr) THEN; IF(PRESENT(nam)) nam = tname; RETURN; END IF
    20142039  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(strStack(PACK(tname, MASK=ll)))//' is not a'
    20152040  CALL msg(TRIM(s)//' a real: '//TRIM(strStack(svals, MASK=ll)), modname)
    20162041END FUNCTION getKeyByIndex_rmmm
    20172042!==============================================================================================================================
    2018 LOGICAL 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
     2043LOGICAL 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
    20242050!------------------------------------------------------------------------------------------------------------------------------
    20252051  CHARACTER(LEN=maxlen) :: s
     
    20272053  LOGICAL,               ALLOCATABLE ::    ll(:)
    20282054  INTEGER,               ALLOCATABLE :: ivals(:)
    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)
     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)
    20312057  IF(lerr) RETURN
    20322058  ivals = str2bool(svals)
    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
     2059  ll = ivals == -1
     2060  lerr = ANY(ll); IF(.NOT.lerr) THEN; val = ivals == 1; IF(PRESENT(nam)) nam = tname; RETURN; END IF
    20362061  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(strStack(tname, MASK=ll))//' is not'
    20372062  CALL msg(TRIM(s)//' a boolean: '//TRIM(strStack(svals, MASK=ll)), modname)
    2038   IF(.NOT.lerr) val = ivals == 1
    20392063END FUNCTION getKeyByIndex_lmmm
    20402064!==============================================================================================================================
     
    20472071!=== TRY TO GET THE KEY NAMED "key" FOR THE TRACER NAMED "tname" IN:                                                        ===
    20482072!===  * ARGUMENT "ky" DATABASE IF SPECIFIED ; OTHERWISE:                                                                    ===
    2049 !===  * IN INTERNAL TRACERS DATABASE "tracers(:)" (IF UNFOUND, IN INTERNAL ISOTOPES DATABASE "isotope%keys(:)")             ===
     2073!===  * IN INTERNAL TRACERS DATABASE "tracers(:)%keys" (IF UNFOUND, IN INTERNAL ISOTOPES DATABASE "isotope%keys(:)")        ===
    20502074!=== THE RETURNED VALUE (STRING, AN INTEGER, A REAL OR A LOGICAL) CAN BE EITHER:                                            ===
    20512075!===  * A SCALAR                                                                                                            ===
     
    21092133  tnam = strHead(delPhase(tname),'_',.TRUE.)                                             !--- Remove phase and tag
    21102134  IF(lerr .AND. PRESENT(ky))         val = fgetKey(ky)                                   !--- "ky"
    2111   IF(lerr .AND. ALLOCATED (tracers)) val = fgetKey(tracers(:))                           !--- "tracers"
     2135  IF(lerr .AND. ALLOCATED (tracers)) val = fgetKey(tracers(:)%keys)                      !--- "tracers"
    21122136  IF(lerr .AND. ASSOCIATED(isotope)) val = fgetKey(isotope%keys(:))                      !--- "isotope"
    21132137  IF(lerr .AND. PRESENT(def)) THEN
     
    21212145 CHARACTER(LEN=maxlen) FUNCTION fgetKey(ky) RESULT(val)
    21222146  TYPE(keys_type),  INTENT(IN)  :: ky(:)
    2123   CHARACTER(LEN=maxlen), ALLOCATABLE :: tname_all(:)
    2124   lerr = SIZE(ky) == 0;                 IF(lerr) RETURN
    2125   lerr = getKey('name', tname_all, ky); IF(lerr) RETURN
    2126            val = fgetKeyIdx(strIdx(tname_all, tname), [keyn], ky, lerr)
    2127   IF(lerr) val = fgetKeyIdx(strIdx(tname_all, tnam ), [keyn], ky, lerr)
     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
    21282152END FUNCTION fgetKey
    21292153
     
    21422166  IF(lerr) RETURN
    21432167  val = str2int(sval)
    2144   lerr = val == -HUGE(1) .AND. sval /= ''
     2168  lerr = val == -HUGE(1)
    21452169  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(tname)//' is not'
    21462170  CALL msg(TRIM(s)//' an integer: '//TRIM(sval), modname, lerr)
     
    21592183  IF(lerr) RETURN
    21602184  val = str2real(sval)
    2161   lerr = val == -HUGE(1.) .AND. sval /= ''
     2185  lerr = val == -HUGE(1.)
    21622186  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(tname)//' is not'
    21632187  CALL msg(TRIM(s)//' a real: '//TRIM(sval), modname, lerr)
     
    21772201  IF(lerr) RETURN
    21782202  ival = str2bool(sval)
    2179   lerr = ival == -1 .AND. sval /= ''
     2203  lerr = ival == -1
    21802204  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(tname)//' is not'
    21812205  CALL msg(TRIM(s)//' a boolean: '//TRIM(sval), modname, lerr)
     
    22122236  IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN
    22132237  val = str2int(svals)
    2214   lerr = ANY(val == -HUGE(1)) .AND. sval /= ''
     2238  lerr = ANY(val == -HUGE(1))
    22152239  s = 'key "'//TRIM(keyn)//'" of '//TRIM(tname)//' is not'
    22162240  CALL msg(TRIM(s)//' an integer: '//TRIM(sval), modname, lerr)
     
    22322256  IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN
    22332257  val = str2real(svals)
    2234   lerr = ANY(val == -HUGE(1.)) .AND. sval /= ''
     2258  lerr = ANY(val == -HUGE(1.))
    22352259  s = 'key "'//TRIM(keyn)//'" of '//TRIM(tname)//' is not'
    22362260  CALL msg(TRIM(s)//' a real: '//TRIM(sval), modname, lerr)
     
    22532277  IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN
    22542278  ivals = str2bool(svals)
    2255   lerr = ANY(ivals == -1) .AND. sval /= ''
     2279  lerr = ANY(ivals == -1)
    22562280  s = 'key "'//TRIM(keyn)//'" of '//TRIM(tname)//' is not'
    22572281  CALL msg(TRIM(s)//' a boolean: '//TRIM(sval), modname, lerr)
     
    22882312  IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN
    22892313  val = str2int(svals)
    2290   lerr = ANY(val == -HUGE(1)) .AND. sval /= ''
     2314  lerr = ANY(val == -HUGE(1))
    22912315  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(tname)//' is not'
    22922316  CALL msg(TRIM(s)//' an integer: '//TRIM(sval), modname, lerr)
     
    23082332  IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN
    23092333  val = str2real(svals)
    2310   lerr = ANY(val == -HUGE(1.)) .AND. sval /= ''
     2334  lerr = ANY(val == -HUGE(1.))
    23112335  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(tname)//' is not'
    23122336  CALL msg(TRIM(s)//' a real: '//TRIM(sval), modname, lerr)
     
    23292353  IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN
    23302354  ivals = str2bool(svals)
    2331   lerr = ANY(ivals == -1) .AND. sval /= ''
     2355  lerr = ANY(ivals == -1)
    23322356  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(tname)//' is not'
    23332357  CALL msg(TRIM(s)//' a boolean: '//TRIM(sval), modname, lerr)
     
    23882412  lerr = .TRUE.
    23892413  IF(PRESENT(ky)) THEN;                 val = fgetKey(ky)                                !--- "ky"
    2390   ELSE IF(ALLOCATED(tracers)) THEN;     val = fgetKey(tracers(:))                        !--- "tracers"
     2414  ELSE IF(ALLOCATED(tracers)) THEN;     val = fgetKey(tracers(:)%keys)                   !--- "tracers"
    23912415     IF(lerr .AND. ASSOCIATED(isotope)) val = fgetKey(isotope%keys(:))                   !--- "isotope"
    23922416  END IF
     
    24032427  TYPE(keys_type),       INTENT(IN)  :: ky(:)
    24042428  LOGICAL,               ALLOCATABLE :: ler(:)
    2405   CHARACTER(LEN=maxlen), ALLOCATABLE :: tname_all(:)
    2406   lerr = SIZE(ky) == 0;                 IF(lerr) RETURN
    2407   lerr = getKey('name', tname_all, ky); IF(lerr) RETURN
     2429  lerr = SIZE(ky) == 0; IF(lerr) RETURN
    24082430  ALLOCATE(ler(SIZE(tname)))
    2409   val = [(fgetKeyIdx(strIdx(tname_all, tname(iq)), keyn, ky, ler(iq)), iq = 1, SIZE(tname))]
     2431  val = [(fgetKeyIdx(strIdx(ky(:)%name, tname(iq)), keyn, ky, ler(iq)), iq = 1, SIZE(tname))]
    24102432  lerr = ANY(ler)
    24112433END FUNCTION fgetKey
     
    24272449  IF(lerr) RETURN
    24282450  val = str2int(svals)
    2429   ll = val == -HUGE(1) .AND. (SIZE(svals) /=1 .OR. svals(1) /= '')
     2451  ll = val == -HUGE(1)
    24302452  lerr = ANY(ll); IF(.NOT.lerr) RETURN
    24312453  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(strStack(tname, MASK=ll))//' is not'
     
    24472469  IF(lerr) RETURN
    24482470  val = str2real(svals)
    2449   ll = val == -HUGE(1.) .AND. (SIZE(svals) /=1 .OR. svals(1) /= '')
     2471  ll = val == -HUGE(1.)
    24502472  lerr = ANY(ll); IF(.NOT.lerr) RETURN
    24512473  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(strStack(tname, MASK=ll))//' is not'
     
    24682490  IF(lerr) RETURN
    24692491  ivals = str2bool(svals)
    2470   ll = ivals == -1 .AND. (SIZE(svals) /=1 .OR. svals(1) /= '')
     2492  ll = ivals == -1
    24712493  lerr = ANY(ll); IF(.NOT.lerr) THEN; val = ivals == 1; RETURN; END IF
    24722494  s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(strStack(tname, MASK=ll))//' is not'
     
    24802502!==============================================================================================================================
    24812503SUBROUTINE setKeysDBase(tracers_, isotopes_, isotope_)
    2482   TYPE(keys_type), OPTIONAL, INTENT(IN) ::  tracers_(:)
     2504  TYPE(trac_type), OPTIONAL, INTENT(IN) ::  tracers_(:)
    24832505  TYPE(isot_type), OPTIONAL, INTENT(IN) :: isotopes_(:)
    24842506  TYPE(isot_type), OPTIONAL, INTENT(IN) :: isotope_
     
    24892511  IF(PRESENT(isotopes_)) THEN; isotopes = isotopes_; ELSE; ALLOCATE(isotopes(0)); END IF
    24902512  IF(PRESENT(isotope_ )) THEN
    2491     ix = strIdx(isotopes(:)%name, isotope_%name)
     2513    ix = strIdx(isotopes(:)%parent, isotope_%parent)
    24922514    IF(ix /= 0) THEN
    24932515      isotopes(ix) = isotope_
     
    25002522!==============================================================================================================================
    25012523SUBROUTINE getKeysDBase(tracers_, isotopes_, isotope_)
    2502   TYPE(keys_type), OPTIONAL, ALLOCATABLE, INTENT(OUT) ::  tracers_(:)
     2524  TYPE(trac_type), OPTIONAL, ALLOCATABLE, INTENT(OUT) ::  tracers_(:)
    25032525  TYPE(isot_type), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: isotopes_(:)
    25042526  TYPE(isot_type), OPTIONAL,              INTENT(OUT) :: isotope_
     
    25072529  IF(PRESENT( tracers_)) THEN;  tracers_ =  tracers; ELSE; ALLOCATE( tracers_(0)); END IF
    25082530  IF(PRESENT(isotopes_)) THEN; isotopes_ = isotopes; ELSE; ALLOCATE(isotopes_(0)); END IF
    2509   IF(PRESENT(isotope_ )) THEN; ix = strIdx(isotopes(:)%name, isotope%name); IF(ix /= 0) isotope_=isotopes(ix); END IF
     2531  IF(PRESENT(isotope_ )) THEN; ix = strIdx(isotopes(:)%parent, isotope%parent); IF(ix /= 0) isotope_=isotopes(ix); END IF
    25102532END SUBROUTINE getKeysDBase
    25112533!==============================================================================================================================
     
    25832605  CHARACTER(LEN=*),             INTENT(IN)    :: tname
    25842606  TYPE(keys_type),              INTENT(IN)    ::  keys
    2585   TYPE(keys_type), ALLOCATABLE, INTENT(INOUT) :: tracs(:)
    2586   TYPE(keys_type), ALLOCATABLE :: tr(:)
     2607  TYPE(trac_type), ALLOCATABLE, INTENT(INOUT) :: tracs(:)
     2608  TYPE(trac_type), ALLOCATABLE :: tr(:)
    25872609  CHARACTER(LEN=maxlen), ALLOCATABLE :: tnames(:)
    25882610  INTEGER :: nt, ix
    25892611  IF(ALLOCATED(tracs)) THEN
    2590      lerr = getKey('name', tnames, ky=tracs(:)); IF(lerr) RETURN
     2612     lerr = getKey('name', tnames, ky=tracs(:)%keys); IF(lerr) RETURN
    25912613     nt = SIZE(tracs)
    25922614     ix = strIdx(tnames, tname)
     
    26002622     ix = 1; ALLOCATE(tracs(1))
    26012623  END IF
    2602   CALL addKey('name', tname, tracs(ix))
    2603   tracs(ix) = keys
     2624  CALL addKey('name', tname, tracs(ix)%keys)
     2625  tracs(ix)%name = tname
     2626  tracs(ix)%keys = keys
    26042627
    26052628END FUNCTION addTracer_1
     
    26162639LOGICAL FUNCTION delTracer_1(tname, tracs) RESULT(lerr)
    26172640  CHARACTER(LEN=*),                     INTENT(IN)    :: tname
    2618   TYPE(keys_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: tracs(:)
    2619   TYPE(keys_type), ALLOCATABLE :: tr(:)
     2641  TYPE(trac_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: tracs(:)
     2642  TYPE(trac_type), ALLOCATABLE :: tr(:)
    26202643  CHARACTER(LEN=maxlen), ALLOCATABLE :: tnames(:)
    26212644  INTEGER :: nt, ix
     
    26232646  IF(fmsg('Can''t remove tracer "'//TRIM(tname)//'" from an empty tracers descriptor', modname, lerr)) RETURN
    26242647  nt = SIZE(tracs)
    2625   lerr = getKey('name', tnames, ky=tracs(:)); IF(lerr) RETURN
     2648  lerr = getKey('name', tnames, ky=tracs(:)%keys); IF(lerr) RETURN
    26262649  ix = strIdx(tnames, tname)
    26272650  CALL msg('Removing tracer "'             //TRIM(tname)//'"', modname, ix /= 0)
     
    26672690
    26682691!==============================================================================================================================
    2669 !======== CONVERT WATER-DERIVED NAMES FROM FORMER TO CURRENT CONVENTION & VICE VERSA ; OTHER NAMES ARE LEFT UNTOUCHED =========
    2670 !===== OLD NAMES STRUCTURE:  H2O[<phase>][_<isotope>][_<tag>] (<phase> from "old_phases",        <isotope> from "oldH2OIso") ==
    2671 !====  NEW NAMES STRUCTURE: <var>[<phase_sep><phase>][_<tag>] (<phase> from "known_phases", <var>='H2O' or from "newH2OIso") ==
     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") ============
    26722694!==============================================================================================================================
    26732695CHARACTER(LEN=maxlen) FUNCTION old2newH2O_1(oldName, iPhase) RESULT(newName)
     
    27022724END FUNCTION old2newH2O_m
    27032725!==============================================================================================================================
     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!==============================================================================================================================
    27042732CHARACTER(LEN=maxlen) FUNCTION new2oldH2O_1(newName, iPhase) RESULT(oldName)
    27052733  CHARACTER(LEN=*),  INTENT(IN)  :: newName
Note: See TracChangeset for help on using the changeset viewer.