Changeset 5183 for LMDZ6/trunk/libf


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

Legend:

Unmodified
Added
Removed
  • LMDZ6/trunk/libf/dyn3d/check_isotopes.F90

    r4984 r5183  
    22   USE strings_mod, ONLY: maxlen, msg, strIdx, strStack, int2str, real2str
    33   USE infotrac,    ONLY: nqtot, niso, nphas, isotope, isoCheck, iqIsoPha, isoSelect, &
    4                           ntiso, iH2O, nzone, tracers, isoName,  itZonIso, getKey
     4                          ntiso, iH2O, nzone, tracers, isoName,  itZonIso
     5   USE iso_params_mod,  ONLY: tnat_H216O, tnat_H217O, tnat_H218O, tnat_HDO, tnat_HTO
     6   USE ioipsl_getincom, ONLY: getin
    57   IMPLICIT NONE
    68   include "dimensions.h"
     
    2022                      deltaDmin =-999.0, &
    2123                      ridicule  = 1e-12
    22    INTEGER, SAVE :: iso_eau, iso_HDO, iso_O18, &
    23                              iso_O17, iso_HTO
    24    LOGICAL, SAVE :: first=.TRUE.
    25    LOGICAL, PARAMETER :: tnat1=.TRUE.
     24   INTEGER, SAVE :: iso_eau, iso_O17, iso_O18, iso_HDO, iso_HTO
     25   LOGICAL, SAVE :: ltnat1, first=.TRUE.
    2626
    2727   modname='check_isotopes'
     
    3030   IF(niso == 0)        RETURN                   !--- No isotopes => finished
    3131   IF(first) THEN
    32       iso_eau = strIdx(isoName,'H216O')
    33       iso_HDO = strIdx(isoName,'HDO')
    34       iso_O18 = strIdx(isoName,'H218O')
    35       iso_O17 = strIdx(isoName,'H217O')
    36       iso_HTO = strIdx(isoName,'HTO')
    37       if (tnat1) then
    38               tnat(:)=1.0
    39       else
    40          IF(getKey('tnat', tnat)) CALL abort_gcm(modname, 'missing isotopic parameter', 1)
    41       endif
     32      ltnat1 = .TRUE.; CALL getin('tnateq1', ltnat1)
     33      ALLOCATE(tnat(niso))
     34      iso_eau = strIdx(isoName,'H216O'); IF(iso_eau /= 0) tnat(iso_eau) = tnat_H216O
     35      iso_O17 = strIdx(isoName,'H217O'); IF(iso_O17 /= 0) tnat(iso_O17) = tnat_H217O
     36      iso_O18 = strIdx(isoName,'H218O'); IF(iso_O18 /= 0) tnat(iso_O18) = tnat_H218O
     37      iso_HDO = strIdx(isoName,'HDO');   IF(iso_HDO /= 0) tnat(iso_HDO) = tnat_HDO
     38      iso_HTO = strIdx(isoName,'HTO');   IF(iso_HTO /= 0) tnat(iso_HTO) = tnat_HTO
     39      IF(ltnat1) tnat(:) = 1.
    4240      first = .FALSE.
    4341   END IF
  • LMDZ6/trunk/libf/dyn3d/dynetat0.F90

    r5084 r5183  
    66! Purpose: Initial state reading.
    77!-------------------------------------------------------------------------------
    8   USE infotrac,    ONLY: nqtot, tracers, niso, iqIsoPha, iH2O, isoName
     8  USE infotrac,    ONLY: nqtot, tracers, niso, iqIsoPha, iH2O, isoName, &
     9                         new2oldH2O, newHNO3, oldHNO3
    910  USE strings_mod, ONLY: maxlen, msg, strStack, real2str, int2str
    1011  USE netcdf,      ONLY: NF90_OPEN,  NF90_NOWRITE, NF90_INQ_VARID, &
    1112                         NF90_CLOSE, NF90_GET_VAR, NF90_NoErr
    12   USE readTracFiles_mod, ONLY: new2oldH2O, newHNO3, oldHNO3, getKey
    1313  USE control_mod, ONLY: planet_type
    1414  USE assert_eq_m, ONLY: assert_eq
     
    1919  USE temps_mod, ONLY: annee_ref, day_ini, day_ref, itau_dyn, start_time
    2020  USE ener_mod, ONLY: etot0,ptot0,ztot0,stot0,ang0
     21#ifdef CPP_IOIPSL
     22  USE IOIPSL,   ONLY: getin
     23#else
     24  USE ioipsl_getincom, ONLY: getin
     25#endif
     26  USE iso_params_mod   ! tnat_* and alpha_ideal_*
    2127
    2228  IMPLICIT NONE
     
    4248  INTEGER :: iq, fID, vID, idecal, iqParent, iName, iZone, iPhase
    4349  REAL    :: time, tnat, alpha_ideal, tab_cntrl(length)    !--- RUN PARAMS TABLE
    44   LOGICAL :: lSkip, ll
    45   LOGICAL,PARAMETER :: tnat1=.TRUE.
     50  LOGICAL :: lSkip, ll, ltnat1
    4651!-------------------------------------------------------------------------------
    4752  modname="dynetat0"
     
    116121  var="temps"
    117122  IF(NF90_INQ_VARID(fID,var,vID)/=NF90_NoErr) THEN
    118     CALL msg('missing field <temps> ; trying with <Time>', modname)
     123    CALL msg('Missing field <temps> ; trying with <Time>', modname)
    119124    var="Time"
    120125    CALL err(NF90_INQ_VARID(fID,var,vID),"inq",var)
     
    133138  ll = NF90_INQ_VARID(fID, 'HNO3tot', vID) /= NF90_NoErr                                 !--- DETECT OLD REPRO start.nc FILE
    134139#endif
     140  ltnat1 = .TRUE.; CALL getin('tnateq1', ltnat1)
    135141  DO iq=1,nqtot
    136142    var = tracers(iq)%name
     
    148154    !--------------------------------------------------------------------------------------------------------------------------
    149155    ELSE IF(NF90_INQ_VARID(fID, oldVar, vID) == NF90_NoErr) THEN                         !=== TRY WITH ALTERNATE NAME
    150       CALL msg('Tracer <'//TRIM(var)//'> is missing => initialized to <'//TRIM(oldVar)//'>', modname)
     156      CALL msg('Missing tracer <'//TRIM(var)//'> => initialized to <'//TRIM(oldVar)//'>', modname)
    151157      CALL err(NF90_GET_VAR(fID,vID,q(:,:,:,iq)),"get",oldVar)
    152158    !--------------------------------------------------------------------------------------------------------------------------
     
    156162      iqParent = tracers(iq)%iqParent
    157163      IF(tracers(iq)%iso_iZone == 0) THEN
    158          if (tnat1) then
    159                  tnat=1.0
    160                  alpha_ideal=1.0
    161                  write(*,*) 'attention dans dynetat0: les alpha_ideal sont a 1'
    162          else
    163           IF(getKey('tnat', tnat, isoName(iName)) .OR. getKey('alpha', alpha_ideal, isoName(iName))) &
    164             CALL abort_gcm(TRIM(modname), 'missing isotopic parameters', 1)
    165          endif
    166          CALL msg('Tracer <'//TRIM(var)//'> is missing => initialized with a simplified Rayleigh distillation law.', modname)
     164         IF(ltnat1) THEN
     165            tnat = 1.0
     166            alpha_ideal = 1.0
     167            CALL msg(' !!!  Beware: alpha_ideal put to 1  !!!', modname)
     168         ELSE
     169            SELECT CASE(isoName(iName))
     170              CASE('H216O'); tnat = tnat_H216O; alpha_ideal = alpha_ideal_H216O
     171              CASE('H217O'); tnat = tnat_H217O; alpha_ideal = alpha_ideal_H217O
     172              CASE('H218O'); tnat = tnat_H218O; alpha_ideal = alpha_ideal_H218O
     173              CASE('HDO');   tnat = tnat_HDO;   alpha_ideal = alpha_ideal_HDO
     174              CASE('HTO');   tnat = tnat_HTO;   alpha_ideal = alpha_ideal_HTO
     175              CASE DEFAULT; CALL abort_gcm(TRIM(modname),'unknown isotope "'//TRIM(isoName(iName))//'" ; check tracer.def file',1)
     176            END SELECT
     177         END IF
     178         CALL msg('Missing tracer <'//TRIM(var)//'> => initialized with a simplified Rayleigh distillation law.', modname)
    167179         q(:,:,:,iq) = q(:,:,:,iqParent)*tnat*(q(:,:,:,iqParent)/30.e-3)**(alpha_ideal-1.)
    168180      ELSE
    169          CALL msg('Tracer <'//TRIM(var)//'> is missing => initialized to its parent isotope concentration.', modname)
     181         CALL msg('Missing tracer <'//TRIM(var)//'> => initialized to its parent isotope concentration.', modname)
    170182         ! Camille 9 mars 2023: attention!! seuls les tags qui correspondent à
    171183         ! izone=izone_init (définie dans isotrac_mod) sont initialisés comme
     
    181193    !--------------------------------------------------------------------------------------------------------------------------
    182194    ELSE                                                                                 !=== MISSING: SET TO 0
    183       CALL msg('Tracer <'//TRIM(var)//'> is missing => initialized to zero', modname)
     195      CALL msg('Missing tracer <'//TRIM(var)//'> => initialized to zero', modname)
    184196      q(:,:,:,iq)=0.
    185197    !--------------------------------------------------------------------------------------------------------------------------
  • LMDZ6/trunk/libf/dyn3d/iniacademic.F90

    r5084 r5183  
    55
    66  USE filtreg_mod, ONLY: inifilr
    7   USE infotrac,    ONLY: nqtot, niso, iqIsoPha, tracers, getKey, isoName
     7  USE infotrac,    ONLY: nqtot, niso, iqIsoPha, tracers, getKey, isoName, addPhase
    88  USE control_mod, ONLY: day_step,planet_type
    99  use exner_hyb_m, only: exner_hyb
     
    2121  USE temps_mod, ONLY: annee_ref, day_ini, day_ref
    2222  USE ener_mod, ONLY: etot0,ptot0,ztot0,stot0,ang0
    23   USE readTracFiles_mod, ONLY: addPhase
    2423  use netcdf, only : NF90_NOWRITE,NF90_OPEN,NF90_NOERR,NF90_INQ_VARID
    2524  use netcdf, only : NF90_CLOSE, NF90_GET_VAR
     25  USE iso_params_mod   ! tnat_* and alpha_ideal_*
    2626
    2727
     
    8080
    8181  REAL zdtvr, tnat, alpha_ideal
    82   LOGICAL,PARAMETER :: tnat1=.true.
     82  LOGICAL :: ltnat1
    8383 
    8484  character(len=*),parameter :: modname="iniacademic"
     
    309309        ! bulk initialization of tracers
    310310        if (planet_type=="earth") then
     311           ltnat1 = .TRUE.; CALL getin('tnateq1', ltnat1)
    311312           ! Earth: first two tracers will be water
    312313           do iq=1,nqtot
     
    322323              iqParent = tracers(iq)%iqParent
    323324              IF(tracers(iq)%iso_iZone == 0) THEN
    324                  if (tnat1) then
    325                          tnat=1.0
    326                          alpha_ideal=1.0
    327                          write(*,*) 'Attention dans iniacademic: alpha_ideal=1'
    328                  else
    329                     IF(getKey('tnat', tnat, isoName(iName)) .OR. getKey('alpha', alpha_ideal, isoName(iName))) &
    330                     CALL abort_gcm(TRIM(modname), 'missing isotopic parameters', 1)
    331                  endif
     325                 IF(ltnat1) THEN
     326                    tnat = 1.0
     327                    alpha_ideal = 1.0
     328                    WRITE(lunout, *)'In '//TRIM(modname)//': !!!  Beware: alpha_ideal put to 1  !!!'
     329                 ELSE
     330                    SELECT CASE(isoName(iName))
     331                      CASE('H216O'); tnat = tnat_H216O; alpha_ideal = alpha_ideal_H216O
     332                      CASE('H217O'); tnat = tnat_H217O; alpha_ideal = alpha_ideal_H217O
     333                      CASE('H218O'); tnat = tnat_H218O; alpha_ideal = alpha_ideal_H218O
     334                      CASE('HDO');   tnat = tnat_HDO;   alpha_ideal = alpha_ideal_HDO
     335                      CASE('HTO');   tnat = tnat_HTO;   alpha_ideal = alpha_ideal_HTO
     336                      CASE DEFAULT
     337                         CALL abort_gcm(TRIM(modname),'unknown isotope "'//TRIM(isoName(iName))//'" ; check tracer.def file',1)
     338                    END SELECT
     339                 END IF
    332340                 q(:,:,iq) = q(:,:,iqParent)*tnat*(q(:,:,iqParent)/30.e-3)**(alpha_ideal-1.)
    333341              ELSE !IF(tracers(iq)%iso_iZone == 0) THEN
  • LMDZ6/trunk/libf/dyn3d/qminimum.F

    r5001 r5183  
    44      SUBROUTINE qminimum( q,nqtot,deltap )
    55
    6       USE infotrac, ONLY: niso, ntiso,iqIsoPha, tracers
     6      USE infotrac, ONLY: niso, ntiso, iqIsoPha, tracers, addPhase
    77      USE strings_mod, ONLY: strIdx
    8       USE readTracFiles_mod, ONLY: addPhase
    98      IMPLICIT none
    109c
  • LMDZ6/trunk/libf/dyn3d_common/infotrac.F90

    r5003 r5183  
    33MODULE infotrac
    44
    5    USE       strings_mod, ONLY: msg, fmsg, maxlen, cat, dispTable, int2str, bool2str, strStack, strParse
    6    USE readTracFiles_mod, ONLY: trac_type, readTracersFiles, tracers, setGeneration, itZonIso, nzone, tran0, isoZone, &
    7         delPhase, niso, getKey, isot_type, processIsotopes,  isotope, maxTableWidth, iqIsoPha, nphas, ixIso, isoPhas, &
    8         addPhase, iH2O, addKey, isoSelect, testTracersFiles, isoKeys, indexUpdate,  iqWIsoPha, nbIso, ntiso, isoName, isoCheck
     5   USE       strings_mod, ONLY: msg, maxlen, cat, dispTable, int2str, bool2str, strStack, strParse, strCount, strIdx
     6   USE readTracFiles_mod, ONLY: readTracersFiles, maxTableWidth,  tisot=>isot_type, addPhase, addKey, iH2O, &
     7        indexUpdate, keys_type, testTracersFiles, processIsotopes, trac=>tracers,   delPhase, getKey, tran0
     8   USE readTracFiles_mod, ONLY: new2oldH2O, newHNO3, oldHNO3
     9
    910   IMPLICIT NONE
    1011
     
    1617   PUBLIC :: nqtot,   nbtr,   nqo,   nqCO2,   nqtottr      !--- Main dimensions
    1718   PUBLIC :: conv_flg, pbl_flg                             !--- Convection & boundary layer activation keys
     19   PUBLIC :: new2oldH2O, newHNO3, oldHNO3                  !--- For backwards compatibility in dynetat0
     20   PUBLIC :: addPhase, delPhase                            !--- Add/remove the phase from the name of a tracer
    1821
    1922   !=== FOR ISOTOPES: General
    2023   PUBLIC :: isot_type, nbIso                              !--- Derived type, full isotopes families database + nb of families
    21    PUBLIC :: isoSelect, ixIso                              !--- Isotopes family selection tool + selected family index
     24   PUBLIC :: isoSelect, ixIso, isoFamilies                 !--- Isotopes families selection tool + selected index + list
    2225   !=== FOR ISOTOPES: Specific to water
    23    PUBLIC :: iH2O                                          !--- H2O isotopes class index
     26   PUBLIC :: iH2O                                          !--- Value of "ixIso" for "H2O" isotopes class
    2427   PUBLIC :: min_qParent, min_qMass, min_ratio             !--- Min. values for various isotopic quantities
    2528   !=== FOR ISOTOPES: Depending on the selected isotopes family
    26    PUBLIC :: isotope, isoKeys                              !--- Selected isotopes database + associated keys (cf. getKey)
    27    PUBLIC :: isoName, isoZone, isoPhas                     !--- Isotopes and tagging zones names, phases
    28    PUBLIC :: niso,    nzone,   nphas,   ntiso              !---  " " numbers + isotopes & tagging tracers number
    29    PUBLIC :: itZonIso                                      !--- idx "it" (in "isoName(1:niso)") = function(tagging idx, isotope idx)
    30    PUBLIC :: iqIsoPha                                      !--- idx "iq" (in "qx") = function(isotope idx, phase idx) + aliases
     29   PUBLIC :: isotope                                       !--- Selected isotopes database (argument of getKey)
     30   PUBLIC :: isoKeys, isoName, isoZone, isoPhas            !--- Isotopes keys & names, tagging zones names, phases
     31   PUBLIC ::    niso,   ntiso,   nzone,   nphas            !--- Number of   "   "
     32   PUBLIC :: itZonIso                                      !--- index "it" in "isoName(1:niso)" = f(tagging idx, isotope idx)
     33   PUBLIC :: iqIsoPha                                      !--- index "iq" in "qx"              = f(isotope idx,   phase idx)
    3134   PUBLIC :: isoCheck                                      !--- Run isotopes checking routines
    3235   !=== FOR BOTH TRACERS AND ISOTOPES
     
    3639!  |--------------------+-----------------------+-----------------+---------------+----------------------------|
    3740!  | water in different |    water tagging      |  water isotopes | other tracers | additional tracers moments |
    38 !  | phases: H2O_[gls|      isotopes         |                 |               |  for higher order schemes  |
     41!  | phases: H2O_[glsrb]|      isotopes         |                 |               |  for higher order schemes  |
    3942!  |--------------------+-----------------------+-----------------+---------------+----------------------------|
    4043!  |                    |                       |                 |               |                            |
     
    5053!  |-----------------------------------------------------------------------------------------------------------|
    5154!  NOTES FOR THIS TABLE:
    52 !  * Used "niso", "nzone" and "ntiso" are components of "isotopes(ip)" for water (isotopes(ip)%parent == 'H2O'),
     55!  * Used "niso", "nzone" and "ntiso" are components of "isotopes(ip)" for water (isotopes(ip)%name == 'H2O'),
    5356!    since water is so far the sole tracers family, except passive CO2, removed from the main tracers table.
    5457!  * For water, "nqo" is equal to the more general field "isotopes(ip)%nphas".
    5558!  * "niso", "nzone", "ntiso", "nphas" are defined for other isotopic tracers families, if any.
    56 !
    57 !=== DERIVED TYPE EMBEDDING MOST OF THE TRACERS-RELATED QUANTITIES (LENGTH: nqtot)
     59!  * If you deal with an isotopes family other than "H2O" ("Sulf" in the example), a good practice is to keep
     60!    track of the isotopes class (of its index) before switching to it at the beginning of the dedicated code:
     61!  - first time (use selection by name and compute the corresponding index iSulf) :
     62!  i0=ixIso; IF(.NOT.isoSelect('Sulf')) CALL abort_gcm("Can't select isotopes class", modname, 1); iS=ixIso
     63!  - next times (use selection by index - "iS" has been computed at first call):
     64!  i0=ixIso; IF(.NOT.isoSelect(iS))     CALL abort_gcm("Can't select isotopes class", modname, 1)
     65!    and to switch back to the original category when you're done with "Sulf":
     66!            IF(.NOT.isoSelect(i0))     CALL abort_gcm("Can't select isotopes class", modname, 1)
     67!    to restore the original isotopes category (before dealing with "Sulf" (most of the time "H2O").
     68!
     69!=== LOCAL DERIVED TYPE "trac_type" EMBEDDING MOST OF THE TRACERS-RELATED QUANTITIES (LENGTH: nqtot)
    5870!    Each entry is accessible using "%" sign.
    5971!  |-------------+------------------------------------------------------+-------------+------------------------+
     
    6173!  |-------------+------------------------------------------------------+-------------+------------------------+
    6274!  | name        | Name (short)                                         | tname       |                        |
     75!  | keys        | key/val pairs accessible with "getKey" routine       | /           |                        |
    6376!  | gen0Name    | Name of the 1st generation ancestor                  | /           |                        |
    6477!  | parent      | Name of the parent                                   | /           |                        |
    6578!  | longName    | Long name (with adv. scheme suffix) for outputs      | ttext       |                        |
    6679!  | type        | Type (so far: tracer or tag)                         | /           | tracer,tag             |
    67 !  | phase       | Phases list ("g"as / "l"iquid / "s"olid)             | /           | [g][l][s]              |
     80!  | phase       | Phases list ("g"as / "l"iquid / "s"olid              |             | [g|l|s|r|b]            |
     81!  |             |              "r"(cloud) / "b"lowing)                 | /           |                        |
    6882!  | component   | Name(s) of the merged/cumulated section(s)           | /           | coma-separated names   |
    6983!  | iGeneration | Generation (>=1)                                     | /           |                        |
     
    7286!  | nqDescen    | Number of the descendants   (all generations)        | nqdesc      | 1:nqtot                |
    7387!  | nqChildren  | Number of childs            (1st generation only)    | nqfils      | 1:nqtot                |
    74 !  | keys        | key/val pairs accessible with "getKey" routine       | /           |                        |
    7588!  | iadv        | Advection scheme number                              | iadv        | 1,2,10-20(exc.15,19),30|
    76 !  | isAdvected  | advected tracers flag (.TRUE. if iadv >= 0)          | /           | nqtrue  .TRUE. values  |
    77 !  | isInPhysics | tracers not extracted from the main table in physics | /           | nqtottr .TRUE. values  |
    7889!  | iso_iGroup  | Isotopes group index in isotopes(:)                  | /           | 1:nbIso                |
    7990!  | iso_iName   | Isotope  name  index in isotopes(iso_iGroup)%trac(:) | iso_indnum  | 1:niso                 |
     
    8798!  |  entry | length | Meaning                                          |    Former name     | Possible values |
    8899!  |-----------------+--------------------------------------------------+--------------------+-----------------+
    89 !  | parent          | Parent tracer (isotopes family name)             |                    |                 |
     100!  | name            | Name of the isotopes class (family)              |                    |                 |
    90101!  | keys   | niso   | Isotopes keys/values pairs list + number         |                    |                 |
    91102!  | trac   | ntiso  | Isotopes + tagging tracers list + number         | / | ntraciso       |                 |
    92103!  | zone   | nzone  | Geographic tagging zones   list + number         | / | ntraceurs_zone |                 |
    93 !  | phase  | nphas  | Phases                     list + number         |                    | [g][l][s], 1:3 |
     104!  | phase  | nphas  | Phases                     list + number         |                    | [g|l|s|r|b] 1:5 |
    94105!  | iqIsoPha        | Index in "qx"           = f(name(1:ntiso)),phas) | iqiso              | 1:nqtot         |
    95106!  | itZonIso        | Index in "trac(1:ntiso)"= f(zone, name(1:niso))  | index_trac         | 1:ntiso         |
    96107!  +-----------------+--------------------------------------------------+--------------------+-----------------+
    97108
     109!------------------------------------------------------------------------------------------------------------------------------
     110   TYPE :: trac_type                                            !=== TYPE FOR A SINGLE TRACER NAMED "name"
     111     CHARACTER(LEN=maxlen) :: name        = ''                  !--- Name of the tracer
     112     TYPE(keys_type)       :: keys                              !--- <key>=<val> pairs vector (general container)
     113     CHARACTER(LEN=maxlen) :: gen0Name    = ''                  !--- First generation ancestor name
     114     CHARACTER(LEN=maxlen) :: parent      = ''                  !--- Parent name
     115     CHARACTER(LEN=maxlen) :: longName    = ''                  !--- Long name (with advection scheme suffix)
     116     CHARACTER(LEN=maxlen) :: type        = 'tracer'            !--- Type  (so far: 'tracer' / 'tag')
     117     CHARACTER(LEN=maxlen) :: phase       = 'g'                 !--- Phase ('g'as / 'l'iquid / 's'olid)
     118     CHARACTER(LEN=maxlen) :: component   = ''                  !--- Coma-separated list of components (Ex: lmdz,inca)
     119     INTEGER               :: iGeneration = -1                  !--- Generation number (>=0)
     120     INTEGER               :: iqParent    = 0                   !--- Parent index
     121     INTEGER,  ALLOCATABLE :: iqDescen(:)                       !--- Descendants index (in growing generation order)
     122     INTEGER               :: nqDescen    = 0                   !--- Number of descendants (all generations)
     123     INTEGER               :: nqChildren  = 0                   !--- Number of children  (first generation)
     124     INTEGER               :: iadv        = 10                  !--- Advection scheme used
     125     INTEGER               :: iso_iGroup  = 0                   !--- Isotopes group index in isotopes(:)
     126     INTEGER               :: iso_iName   = 0                   !--- Isotope  name  index in isotopes(iso_iGroup)%trac(:)
     127     INTEGER               :: iso_iZone   = 0                   !--- Isotope  zone  index in isotopes(iso_iGroup)%zone(:)
     128     INTEGER               :: iso_iPhase  = 0                   !--- Isotope  phase index in isotopes(iso_iGroup)%phase
     129   END TYPE trac_type
     130!------------------------------------------------------------------------------------------------------------------------------
     131  TYPE :: isot_type                                             !=== TYPE FOR THE ISOTOPES FAMILY DESCENDING ON TRACER "name"
     132    CHARACTER(LEN=maxlen)              :: name                  !--- Isotopes family name (ex: H2O)
     133    TYPE(keys_type),       ALLOCATABLE :: keys(:)               !--- Isotopes keys/values pairs list     (length: niso)
     134    LOGICAL                            :: check=.FALSE.         !--- Flag for checking routines triggering
     135    CHARACTER(LEN=maxlen), ALLOCATABLE :: trac(:)               !--- Isotopes + tagging tracers list     (length: ntiso)
     136    CHARACTER(LEN=maxlen), ALLOCATABLE :: zone(:)               !--- Geographic tagging zones names list (length: nzone)
     137    CHARACTER(LEN=maxlen)              :: phase = 'g'           !--- Phases list: [g|l|s|r|b]            (length: nphas)
     138    INTEGER                            :: niso  = 0             !--- Number of isotopes, excluding tagging tracers
     139    INTEGER                            :: ntiso = 0             !--- Number of isotopes, including tagging tracers
     140    INTEGER                            :: nzone = 0             !--- Number of geographic tagging zones
     141    INTEGER                            :: nphas = 0             !--- Number of phases
     142    INTEGER,               ALLOCATABLE :: iqIsoPha(:,:)         !--- Idx in "tracers(1:nqtot)" = f(     name(1:ntiso) ,phas)
     143    INTEGER,               ALLOCATABLE :: itZonIso(:,:)         !--- Idx in "trac(1:ntiso)"    = f(zone,name(1:niso))
     144  END TYPE isot_type
     145!------------------------------------------------------------------------------------------------------------------------------
     146  INTERFACE isoSelect; MODULE PROCEDURE isoSelectByIndex, isoSelectByName; END INTERFACE isoSelect
     147!------------------------------------------------------------------------------------------------------------------------------
     148
     149   !=== THRESHOLDS FOR WATER
    98150   REAL, PARAMETER :: min_qParent = 1.e-30, min_qMass = 1.e-18, min_ratio = 1.e-16 ! MVals et CRisi
    99151
    100152   !=== DIMENSIONS OF THE TRACERS TABLES AND OTHER SCALAR VARIABLES
    101    INTEGER,               SAVE :: nqtot,  &                     !--- Tracers nb in dynamics (incl. higher moments + H2O)
    102                                   nbtr,   &                     !--- Tracers nb in physics  (excl. higher moments + H2O)
    103                                   nqo,    &                     !--- Number of water phases
     153   INTEGER,               SAVE :: nqtot,   &                    !--- Tracers nb in dynamics (incl. higher moments + H2O)
     154                                  nbtr,    &                    !--- Tracers nb in physics  (excl. higher moments + H2O)
     155                                  nqo,     &                    !--- Number of water phases
    104156                                  nqtottr, &                    !--- Number of tracers passed to phytrac (TO BE DELETED ?)
    105157                                  nqCO2                         !--- Number of tracers of CO2  (ThL)
    106    CHARACTER(LEN=maxlen), SAVE :: type_trac                     !--- Keyword for tracers type
     158   CHARACTER(LEN=maxlen), SAVE :: type_trac                     !--- Keyword for tracers type(s)
     159
     160   !=== NUMBER AND LIST OF DEFINED ISOTOPES FAMILIES
     161   INTEGER,               SAVE              :: nbIso            !--- Number of defined isotopes classes
     162   CHARACTER(LEN=maxlen), SAVE, ALLOCATABLE :: isoFamilies(:)   !--- Generation 0 tracer name for each isotopes family (nbIso)
     163
     164   !=== QUANTITIES RELATED TO THE CURRENTLY SELECTED ISOTOPES CLASS (USUALLY H2O)
     165   TYPE(isot_type),       SAVE, POINTER :: isotope              !--- Selected isotopes database (=isotopes(ixIso))
     166   TYPE(keys_type),       SAVE, POINTER :: isoKeys(:)           !--- Database to get isotopes keys using "getKey"       (niso)
     167   CHARACTER(LEN=maxlen), SAVE, POINTER :: isoName(:),      &   !--- Isotopes list including tagging tracers, no phase (ntiso)
     168                                           isoZone(:),      &   !--- Geographic tagging zones list                     (nzone)
     169                                           isoPhas              !--- Used phases names ([g|l|s|r|b])                   (nphas)
     170   INTEGER,               SAVE, POINTER :: itZonIso(:,:),   &   !--- Idx "it" in isoName(1:niso) = f(tagging idx, isotope idx)
     171                                           iqIsoPha(:,:)        !--- Idx "iq" in qx              = f(isotope idx,   phase idx)
     172   INTEGER,               SAVE          :: ixIso,           &   !--- Idx in "isoFamilies" of currently selectd class
     173                                           niso,            &   !--- Number of isotopes
     174                                           ntiso,           &   !--- Number of isotopes + tagging tracers
     175                                           nzone,           &   !--- Number of tagging zones
     176                                           nphas                !--- Number of phases
     177   LOGICAL,               SAVE          :: isoCheck             !--- Isotopes checking routines triggering flag
    107178
    108179   !=== VARIABLES FOR INCA
    109    INTEGER,               SAVE, ALLOCATABLE :: conv_flg(:), &   !--- Convection     activation ; needed for INCA        (nbtr)
    110                                                 pbl_flg(:)      !--- Boundary layer activation ; needed for INCA        (nbtr)
     180   INTEGER, DIMENSION(:), SAVE, ALLOCATABLE :: &
     181                    conv_flg, pbl_flg                           !--- Convection / boundary layer activation (nbtr)
     182
     183   !=== TRACERS/ISOTOPES DESCRIPTORS: EFFECTIVE STORAGE (LOCAL DERIVED TYPES)
     184   TYPE(trac_type), SAVE, ALLOCATABLE, TARGET ::  tracers(:)
     185   TYPE(isot_type), SAVE, ALLOCATABLE, TARGET :: isotopes(:)
    111186
    112187CONTAINS
     
    114189SUBROUTINE init_infotrac
    115190   USE control_mod, ONLY: planet_type
     191#ifdef CPP_IOIPSL
     192    USE IOIPSL, ONLY: getin
     193#else
     194    USE ioipsl_getincom, only: getin
     195#endif
     196#ifdef CPP_PARA
     197   USE parallel_lmdz, ONLY: is_master
     198#endif
    116199#ifdef REPROBUS
    117    USE CHEM_REP,    ONLY: Init_chem_rep_trac
     200   USE CHEM_REP, ONLY: Init_chem_rep_trac
    118201#endif
    119202   IMPLICIT NONE
     
    142225!------------------------------------------------------------------------------------------------------------------------------
    143226! Local variables
    144    INTEGER, ALLOCATABLE :: hadv(:), vadv(:)                          !--- Horizontal/vertical transport scheme number
     227   INTEGER, ALLOCATABLE :: hadv(:), vadv(:), itmp(:)                 !--- Horizontal/vertical transport scheme number
    145228#ifdef INCA
    146229   INTEGER, ALLOCATABLE :: had (:), hadv_inca(:), conv_flg_inca(:), &!--- Variables specific to INCA
     
    149232   INTEGER :: nqINCA
    150233#endif
     234#ifndef CPP_PARA
     235   LOGICAL               :: is_master=.TRUE.
     236#endif
    151237   CHARACTER(LEN=2)      ::   suff(9)                                !--- Suffixes for schemes of order 3 or 4 (Prather)
    152238   CHARACTER(LEN=3)      :: descrq(30)                               !--- Advection scheme description tags
    153    CHARACTER(LEN=maxlen) :: msg1, texp, ttp                          !--- Strings for messages and expanded tracers type
     239   CHARACTER(LEN=maxlen) :: msg1, texp, ttp, ky, nam, val            !--- Strings for messages and expanded tracers type
    154240   INTEGER :: fType                                                  !--- Tracers description file type ; 0: none
    155241                                                                     !--- 1/2/3: "traceur.def"/"tracer.def"/"tracer_*.def"
    156242   INTEGER :: nqtrue                                                 !--- Tracers nb from tracer.def (no higher order moments)
    157243   INTEGER :: iad                                                    !--- Advection scheme number
    158    INTEGER :: iq, jq, nt, im, nm                                     !--- Indexes and temporary variables
    159    LOGICAL :: lerr, ll
     244   INTEGER :: iq, jq, it, nt, im, nm, ig                             !--- Indexes and temporary variables
     245   LOGICAL :: lerr, lInit
     246   TYPE(keys_type), ALLOCATABLE, TARGET :: tra(:)                    !--- Tracers  descriptor as in readTracFiles_mod
     247   TYPE(tisot),     ALLOCATABLE         :: iso(:)                    !--- Isotopes descriptor as in readTracFiles_mod
    160248   TYPE(trac_type), ALLOCATABLE, TARGET :: ttr(:)
    161    TYPE(trac_type), POINTER             :: t1, t(:)
    162    CHARACTER(LEN=maxlen),   ALLOCATABLE :: types_trac(:)  !--- Keyword for tracers type(s), parsed version
    163 
     249   TYPE(trac_type), POINTER             :: t(:), t1
     250   TYPE(keys_type), POINTER             :: k(:)
     251   CHARACTER(LEN=maxlen),   ALLOCATABLE :: types_trac(:)             !--- Keywords for tracers type(s), parsed version
    164252   CHARACTER(LEN=*), PARAMETER :: modname="init_infotrac"
    165253!------------------------------------------------------------------------------------------------------------------------------
     
    171259   descrq(10:20) = ['VL1','VLP','FH1','FH2','VLH','   ','PPM','PPS','PPP','   ','SLP']
    172260   descrq(30)    =  'PRA'
    173    
    174    CALL msg('type_trac = "'//TRIM(type_trac)//'"', modname)
    175 
    176    lerr=strParse(type_trac, '|', types_trac, n=nt)
    177    IF (nt .GT. 1) THEN
    178       IF (nt .GT. 2) CALL abort_gcm(modname, 'you need to modify type_trac, this version is not supported by lmdz', 1)
    179       if (nt .EQ. 2) type_trac=types_trac(2)
    180    ENDIF
    181 
    182 
    183    
     261
     262   CALL msg('type_trac = "'//TRIM(type_trac)//'"', modname, is_master)
     263   IF(strCount(type_trac, '|', nt)) CALL abort_gcm(modname, 'Could''nt parse the "type_trac" string with delimiter "|"', 1)
     264   IF(nt >= 3) CALL abort_gcm(modname, 'you need to modify type_trac, this version is not supported by lmdz', 1)
     265   IF(strParse(type_trac, '|', types_trac, n=nt)) CALL abort_gcm(modname, "couldn't parse "//'"type_trac"', 1)
     266   IF(nt == 2) type_trac = types_trac(2) ! TO BE DELETED SOON
     267
     268   lInit = .NOT.ALLOCATED(trac)
     269
     270!##############################################################################################################################
     271   IF(lInit .AND. is_master) THEN                                    !=== SKIPED IF ALREADY DONE
     272!##############################################################################################################################
    184273   !--- MESSAGE ABOUT THE CHOSEN CONFIGURATION
    185274   msg1 = 'For type_trac = "'//TRIM(type_trac)//'":'
     
    209298#endif
    210299   END SELECT
    211 
    212    nqCO2 = COUNT( [type_trac == 'inco', type_trac == 'co2i'] )
    213 
    214 !==============================================================================================================================
    215 ! 1) Get the numbers of: true (first order only) tracers "nqtrue", water tracers "nqo" (vapor/liquid/solid)
    216 !==============================================================================================================================
    217    texp = type_trac                                                  !=== EXPANDED VERSION OF "type_trac", WITH "|" SEPARATOR
     300!##############################################################################################################################
     301   END IF
     302!##############################################################################################################################
     303
     304!==============================================================================================================================
     305! 0) DETERMINE THE TYPE OF THE INPUT TRACERS DESCRIPTION FILE AND READ IT ; TRANSFER THE NEEDED QUANTITIES TO LOCAL "tracers".
     306!==============================================================================================================================
     307   texp = type_trac                                                            !=== EXPANDED (WITH "|" SEPARATOR) "type_trac"
    218308   IF(texp == 'inco') texp = 'co2i|inca'
    219309   IF(texp /= 'lmdz') texp = 'lmdz|'//TRIM(texp)
    220 
    221    !=== DETERMINE THE TYPE OF THE INPUT TRACERS DESCRIPTION FILE
    222    IF(testTracersFiles(modname, texp, fType, .TRUE.)) CALL abort_gcm(modname, 'problem with tracers file(s)',1)
     310   IF(testTracersFiles(modname, texp, fType, lInit.AND.is_master)) CALL abort_gcm(modname, 'problem with tracers file(s)',1)
    223311   ttp = type_trac; IF(fType /= 1) ttp = texp
    224 
    225    IF(readTracersFiles(ttp, lRepr=type_trac=='repr')) CALL abort_gcm(modname, 'problem with tracers file(s)',1)
    226312   !---------------------------------------------------------------------------------------------------------------------------
    227    IF(fType == 0) CALL abort_gcm(modname, 'Missing tracers file: "traceur.def", "tracer.def" or "tracer_<keyword>.def file.',1)
     313   IF(fType == 0) CALL abort_gcm(modname, 'Missing "traceur.def", "tracer.def" or "tracer_<keyword>.def tracers file.',1)
    228314   !---------------------------------------------------------------------------------------------------------------------------
    229    IF(fType == 1 .AND. ANY(['inca','inco']==type_trac)) THEN         !=== FOUND OLD STYLE INCA "traceur.def"
     315   IF(fType == 1 .AND. ANY(['inca', 'inco'] == type_trac) .AND. lInit) &       !=== FOUND OLD STYLE INCA "traceur.def"
     316      CALL abort_gcm(modname, 'retro-compatibility with old-style INCA traceur.def files has been disabled.', 1)
    230317   !---------------------------------------------------------------------------------------------------------------------------
     318
     319!##############################################################################################################################
     320   IF(lInit) THEN
     321      IF(readTracersFiles(ttp, tra, type_trac == 'repr')) CALL abort_gcm(modname, 'problem with tracers file(s)',1)
     322   ELSE
     323      tra = trac
     324   END IF
     325   CALL msg('No tracers description file(s) reading needed: already done', modname, .NOT.lInit.AND.is_master)
     326!##############################################################################################################################
     327
     328   !--- POPULATE SOME EXPLICIT (ACCESSIBLE THROUGH "%") KEYS OF THE LOCAL TRACERS DESCRIPTION DERIVED TYPE
     329   !    To be defined: iqParent, iq/nqDescen, nqChildren (in indexUpdate), longName, iso_i*, iadv (later)
     330   ALLOCATE(tracers(SIZE(tra)))
     331   DO iq = 1, SIZE(tra); t1 => tracers(iq)
     332      t1%keys = tra(iq)
     333      msg1 = '" for tracer nr. '//TRIM(int2str(iq))
     334      ky='name       '; IF(getKey(ky, t1%name,        iq, tra)) CALL abort_gcm(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1)
     335      msg1 = '" for "'//TRIM(t1%name)//'"'
     336      ky='gen0Name   '; IF(getKey(ky, t1%gen0Name,    iq, tra)) CALL abort_gcm(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1)
     337      ky='parent     '; IF(getKey(ky, t1%parent,      iq, tra)) CALL abort_gcm(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1)
     338      ky='type       '; IF(getKey(ky, t1%type,        iq, tra)) CALL abort_gcm(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1)
     339      ky='phase      '; IF(getKey(ky, t1%phase,       iq, tra)) CALL abort_gcm(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1)
     340      ky='component  '; IF(getKey(ky, t1%component,   iq, tra)) CALL abort_gcm(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1)
     341      ky='iGeneration'; IF(getKey(ky, t1%iGeneration, iq, tra)) CALL abort_gcm(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1)
     342   END DO
     343
     344!==============================================================================================================================
     345! 1) Get various numbers: "nqtrue" (first order only tracers), "nqo" (water phases), 'nbtr' (tracers passed to physics), etc.
     346!==============================================================================================================================
     347   nqtrue = SIZE(tracers)                                                                               !--- "true" tracers
     348   nqo    =      COUNT(tracers(:)%component == 'lmdz' .AND. delPhase(tracers(:)%name)     == 'H2O')     !--- Water phases
     349   nbtr = nqtrue-COUNT(tracers(:)%component == 'lmdz' .AND. delPhase(tracers(:)%gen0Name) == 'H2O')     !--- Passed to phytrac
     350   nqCO2  =      COUNT( [type_trac == 'inco', type_trac == 'co2i'] )
    231351#ifdef INCA
    232       nqo = SIZE(tracers) - nqCO2
    233       CALL Init_chem_inca_trac(nqINCA)                               !--- Get nqINCA from INCA
    234       nbtr = nqINCA + nqCO2                                          !--- Number of tracers passed to phytrac
    235       nqtrue = nbtr + nqo                                            !--- Total number of "true" tracers
    236       IF(ALL([2,3] /= nqo)) CALL abort_gcm(modname, 'Only 2 or 3 water phases allowed ; found nqo='//TRIM(int2str(nqo)), 1)
    237       ALLOCATE(hadv(nqtrue), hadv_inca(nqINCA), conv_flg_inca(nqINCA), solsym_inca(nqINCA))
    238       ALLOCATE(vadv(nqtrue), vadv_inca(nqINCA),  pbl_flg_inca(nqINCA))
    239       CALL init_transport(solsym_inca, conv_flg_inca, pbl_flg_inca, hadv_inca, vadv_inca)
    240       ALLOCATE(ttr(nqtrue))
    241       ttr(1:nqo+nqCO2)                  = tracers
    242       ttr(1    :      nqo   )%component = 'lmdz'
    243       ttr(1+nqo:nqCO2+nqo   )%component = 'co2i'
    244       ttr(1+nqo+nqCO2:nqtrue)%component = 'inca'
    245       ttr(1+nqo      :nqtrue)%name      = [('CO2     ', iq=1, nqCO2), solsym_inca]
    246       ttr(1+nqo+nqCO2:nqtrue)%parent    = tran0
    247       ttr(1+nqo+nqCO2:nqtrue)%phase     = 'g'
    248       lerr = getKey('hadv', had, ky=tracers(:)%keys)
    249       lerr = getKey('vadv', vad, ky=tracers(:)%keys)
    250       hadv(1:nqo+nqCO2) = had(:); hadv(1+nqo+nqCO2:nqtrue) = hadv_inca
    251       vadv(1:nqo+nqCO2) = vad(:); vadv(1+nqo+nqCO2:nqtrue) = vadv_inca
    252       CALL MOVE_ALLOC(FROM=ttr, TO=tracers)
    253       DO iq = 1, nqtrue
    254          t1 => tracers(iq)
    255          CALL addKey('name',      t1%name,      t1%keys)
    256          CALL addKey('component', t1%component, t1%keys)
    257          CALL addKey('parent',    t1%parent,    t1%keys)
    258          CALL addKey('phase',     t1%phase,     t1%keys)
    259       END DO
    260       IF(setGeneration(tracers)) CALL abort_gcm(modname,'See above',1) !- SET FIELDS %iGeneration, %gen0Name
    261       DEALLOCATE(had, hadv_inca, vad, vadv_inca, conv_flg_inca, pbl_flg_inca, solsym_inca)
    262 #endif
    263    !---------------------------------------------------------------------------------------------------------------------------
    264    ELSE                                                              !=== OTHER CASES (OLD OR NEW FORMAT, NO INCA MODULE)
    265    !---------------------------------------------------------------------------------------------------------------------------
    266       nqo    =        COUNT(delPhase(tracers(:)%name)     == 'H2O' &
    267                                .AND. tracers(:)%component == 'lmdz') !--- Number of water phases
    268       nqtrue = SIZE(tracers)                                         !--- Total number of "true" tracers
    269       nbtr   = nqtrue-COUNT(delPhase(tracers(:)%gen0Name) == 'H2O' &
    270                                .AND. tracers(:)%component == 'lmdz') !--- Number of tracers passed to phytrac
    271 #ifdef INCA
    272       nqINCA = COUNT(tracers(:)%component == 'inca')
    273 #endif
    274       lerr = getKey('hadv', hadv, ky=tracers(:)%keys)
    275       lerr = getKey('vadv', vadv, ky=tracers(:)%keys)
    276    !---------------------------------------------------------------------------------------------------------------------------
    277    END IF
    278    !---------------------------------------------------------------------------------------------------------------------------
    279 
     352   nqINCA =      COUNT(tracers(:)%component == 'inca')
     353#endif
    280354#ifdef REPROBUS
    281    !--- Transfert the number of tracers to Reprobus
    282    CALL Init_chem_rep_trac(nbtr, nqo, tracers(:)%name)
    283 
    284 #endif
     355   CALL Init_chem_rep_trac(nbtr, nqo, tracers(:)%name)                         !--- Transfert the number of tracers to Reprobus
     356#endif
     357
    285358!==============================================================================================================================
    286359! 2) Calculate nqtot, number of tracers needed (greater if advection schemes 20 or 30 have been chosen).
    287360!==============================================================================================================================
     361   IF(getKey('hadv', hadv, ky=tra)) CALL abort_gcm(modname, 'missing key "hadv"', 1)
     362   IF(getKey('vadv', vadv, ky=tra)) CALL abort_gcm(modname, 'missing key "vadv"', 1)
    288363   DO iq = 1, nqtrue
    289364      IF( hadv(iq)<20 .OR. (ANY(hadv(iq)==[20,30]) .AND. hadv(iq)==vadv(iq)) ) CYCLE
     
    303378
    304379!==============================================================================================================================
    305 ! 3) Determine the advection scheme choice for water and tracers "iadv" and the fields long name, isAdvected.
     380! 3) Determine the advection scheme choice for water and tracers "iadv" and the fields long name.
    306381!     iadv = 1    "LMDZ-specific humidity transport" (for H2O vapour)          LMV
    307382!     iadv = 2    backward                           (for H2O liquid)          BAK
     
    321396!==============================================================================================================================
    322397   ALLOCATE(ttr(nqtot))
    323    jq = nqtrue+1; tracers(:)%iadv = -1
     398   jq = nqtrue+1
    324399   DO iq = 1, nqtrue
    325400      t1 => tracers(iq)
     
    332407      IF(iad == -1) CALL abort_gcm(modname, msg1, 1)
    333408
    334       !--- SET FIELDS %longName, %iadv, %isAdvected, %isInPhysics
     409      !--- SET FIELDS longName, iadv
     410      t1%iadv       = iad
    335411      t1%longName   = t1%name; IF(iad > 0) t1%longName=TRIM(t1%name)//descrq(iad)
    336       t1%iadv       = iad
    337       t1%isAdvected = iad >= 0
    338       t1%isInPhysics= delPhase(t1%gen0Name) /= 'H2O' &
    339                           .OR. t1%component /= 'lmdz' !=== OTHER EXCEPTIONS TO BE ADDED: CO2i, SURSATURATED WATER CLOUD...
    340412      ttr(iq)       = t1
    341413
     
    347419      ttr(jq+1:jq+nm)             = t1
    348420      ttr(jq+1:jq+nm)%name        = [ (TRIM(t1%name)    //'-'//TRIM(suff(im)), im=1, nm) ]
     421      ttr(jq+1:jq+nm)%gen0Name    = [ (TRIM(t1%name)    //'-'//TRIM(suff(im)), im=1, nm) ]
    349422      ttr(jq+1:jq+nm)%parent      = [ (TRIM(t1%parent)  //'-'//TRIM(suff(im)), im=1, nm) ]
    350423      ttr(jq+1:jq+nm)%longName    = [ (TRIM(t1%longName)//'-'//TRIM(suff(im)), im=1, nm) ]
    351424      ttr(jq+1:jq+nm)%iadv        = [ (-iad,    im=1, nm) ]
    352       ttr(jq+1:jq+nm)%isAdvected  = [ (.FALSE., im=1, nm) ]
    353425      jq = jq + nm
    354426   END DO
     
    356428   CALL MOVE_ALLOC(FROM=ttr, TO=tracers)
    357429
    358    !--- SET FIELDS %iqParent, %nqChildren, %iGeneration, %iqDescen, %nqDescen
    359    IF(indexUpdate(tracers)) CALL abort_gcm(modname, 'problem with tracers indices update', 1)
     430   !--- SET FIELDS iqParent, iqDescen, nqDescen, nqChildren
     431   IF(indexUpdate(tracers%keys)) CALL abort_gcm(modname, 'problem with tracers indices update', 1)
     432   k => tracers(:)%keys
     433   DO iq = 1, SIZE(tracers); t1 => tracers(iq); msg1 = '" for "'//TRIM(t1%name)//'"'
     434      ky='iqParent  '; IF(getKey(ky, t1%iqParent,   iq, k)) CALL abort_gcm(modname, 'missing key "'//TRIM(ky)//TRIM(msg1), 1)
     435      ky='iqDescen  '; IF(getKey(ky, t1%iqDescen,   iq, k)) CALL abort_gcm(modname, 'missing key "'//TRIM(ky)//TRIM(msg1), 1)
     436      ky='nqDescen  '; IF(getKey(ky, t1%nqDescen,   iq, k)) CALL abort_gcm(modname, 'missing key "'//TRIM(ky)//TRIM(msg1), 1)
     437      ky='nqChildren'; IF(getKey(ky, t1%nqChildren, iq, k)) CALL abort_gcm(modname, 'missing key "'//TRIM(ky)//TRIM(msg1), 1)
     438   END DO
    360439
    361440   !=== TEST ADVECTION SCHEME
    362    DO iq=1,nqtot ; t1 => tracers(iq); iad = t1%iadv
     441   DO iq = 1, nqtot ; t1 => tracers(iq)
     442      iad = t1%iadv
     443      ig  = t1%iGeneration
     444      nam = t1%name
     445      val = 'iadv='//TRIM(int2str(iad))
    363446
    364447      !--- ONLY TESTED VALUES FOR TRACERS FOR NOW:               iadv = 14, 10 (and 0 for non-transported tracers)
    365       IF(ALL([10,14,0] /= iad)) &
    366          CALL abort_gcm(modname, 'Not tested for iadv='//TRIM(int2str(iad))//' ; 10 or 14 only are allowed !', 1)
    367 
    368       !--- ONLY TESTED VALUES FOR PARENTS HAVING CHILDS FOR NOW: iadv = 14, 10 (PARENTS: TRACERS OF GENERATION 1)
    369       IF(ALL([10,14] /= iad) .AND. t1%iGeneration == 1 .AND. ANY(tracers(:)%iGeneration > 1)) &
    370          CALL abort_gcm(modname, 'iadv='//TRIM(int2str(iad))//' not implemented for parents ; 10 or 14 only are allowed !', 1)
    371 
    372       !--- ONLY TESTED VALUES FOR CHILDS FOR NOW:                iadv = 10     (CHILDS:  TRACERS OF GENERATION GREATER THAN 1)
    373       IF(fmsg('WARNING ! iadv='//TRIM(int2str(iad))//' not implemented for childs. Setting iadv=10 for "'//TRIM(t1%name)//'"',&
    374          modname, iad /= 10 .AND. t1%iGeneration > 1)) t1%iadv = 10
    375 
    376       !--- ONLY VALID SCHEME NUMBER FOR WATER VAPOUR:            iadv = 14
    377       ll = t1%name /= addPhase('H2O','g')
    378       IF(fmsg('WARNING ! iadv=14 is valid for water vapour only. Setting iadv=10 for "'//TRIM(t1%name)//'".', &
    379          modname, iad == 14 .AND. ll))                 t1%iadv = 10
     448      IF(ALL([10,14,0] /= iad)) CALL abort_gcm(modname, TRIM(val)//' has not been tested yet ; 10 or 14 only are allowed !', 1)
     449
     450      !--- ONLY TESTED VALUES SO FAR FOR PARENTS HAVING CHILDREN: iadv = 14, 10 (PARENTS: TRACERS OF GENERATION 0)
     451      IF(ALL([10,14] /= iad) .AND. ig == 0 .AND. ANY(tracers(:)%parent==nam)) &
     452         CALL abort_gcm(modname, TRIM(val)//' is not implemented for parents ; 10 or 14 only are allowed !', 1)
     453
     454      !--- ONLY TESTED VALUES SO FAR FOR DESCENDANTS (TRACERS OF GENERATION > 0): iadv = 10 ; WATER VAPOUR: iadv = 14
     455      lerr = iad /= 10 .AND. ig > 0;                     IF(lerr) tracers(iq)%iadv = 10
     456      CALL msg('WARNING! '//TRIM(val)//  ' not implemented for children. Setting iadv=10 for "'//TRIM(nam)//'"', modname, lerr)
     457      lerr = iad == 14 .AND. nam /= addPhase('H2O','g'); IF(lerr) tracers(iq)%iadv = 10
     458      CALL msg('WARNING! '//TRIM(val)//' is valid for water vapour only. Setting iadv=10 for "'//TRIM(nam)//'"', modname, lerr)
    380459   END DO
    381460
    382    !=== READ PHYSICAL PARAMETERS FOR ISOTOPES ; DONE HERE BECAUSE dynetat0 AND iniacademic NEED "tnat" AND "alpha_ideal"
    383    niso = 0; nzone = 0; nphas = nqo; ntiso = 0; isoCheck = .FALSE.
    384    IF(processIsotopes()) CALL abort_gcm(modname, 'problem when processing isotopes parameters', 1)
     461   !=== DETERMINE ISOTOPES RELATED PARAMETERS ; DEFINE THE EXPLICIT KEYS iso_i*
     462   IF(processIsotopes(tracers%keys, iso)) CALL abort_gcm(modname, 'problem while processing isotopes parameters', 1)
     463
     464   !--- POPULATE SOME EXPLICIT (ACCESSIBLE THROUGH "%") KEYS OF THE LOCAL ISOTOPES DESCRIPTION DERIVED TYPE
     465   nbIso = SIZE(iso)
     466   ALLOCATE(isotopes(nbIso))
     467   IF(nbIso /= 0) THEN
     468      k => tracers(:)%keys
     469      IF(getKey('iso_iGroup', itmp, ky=k)) CALL abort_gcm(modname, 'missing key "iso_iGroup"', 1); tracers%iso_iGroup=itmp
     470      IF(getKey('iso_iName',  itmp, ky=k)) CALL abort_gcm(modname, 'missing key "iso_iName"',  1); tracers%iso_iName =itmp
     471      IF(getKey('iso_iZone',  itmp, ky=k)) CALL abort_gcm(modname, 'missing key "iso_iZone"',  1); tracers%iso_iZone =itmp
     472      IF(getKey('iso_iPhas',  itmp, ky=k)) CALL abort_gcm(modname, 'missing key "iso_iPhas"',  1); tracers%iso_iPhase=itmp
     473      isotopes(:)%name  = iso(:)%name                           !--- Isotopes family name (ex: H2O)
     474      isotopes(:)%phase = iso(:)%phase                          !--- Phases list: [g][l][s]              (length: nphas)
     475      isotopes(:)%niso  = iso(:)%niso                           !--- Number of isotopes, excluding tagging tracers
     476      isotopes(:)%ntiso = iso(:)%ntiso                          !--- Number of isotopes, including tagging tracers
     477      isotopes(:)%nzone = iso(:)%nzone                          !--- Number of geographic tagging zones
     478      isotopes(:)%nphas = iso(:)%nphas                          !--- Number of phases
     479      isotopes(:)%check = .FALSE.                               !--- Flag for checking routines triggering
     480      CALL getin('ok_iso_verif', isotopes(:)%check)
     481      DO it = 1, nbIso
     482         isotopes(it)%keys     = iso(it)%keys                   !--- Isotopes keys/values pairs list     (length: niso)
     483         isotopes(it)%trac     = iso(it)%trac                   !--- Isotopes + tagging tracers list     (length: ntiso)
     484         isotopes(it)%zone     = iso(it)%zone                   !--- Geographic tagging zones names list (length: nzone)
     485         isotopes(it)%iqIsoPha = iso(it)%iqIsoPha(:,:)          !--- Idx in "tracers(1:nqtot)" = f(name(1:ntiso)),phas)
     486         isotopes(it)%itZonIso = iso(it)%itZonIso(:,:)          !--- Idx in "tracers(1:ntiso)" = f(  zone,name(1:niso))
     487      END DO
     488      IF(isoSelect(1, .TRUE.)) CALL abort_gcm(modname, "Can't select the first isotopes family", 1)
     489      IF(.NOT.isoSelect('H2O', .TRUE.)) iH2O = ixIso
     490   END IF
     491   isoFamilies = isotopes(:)%name
    385492
    386493   !--- Convection / boundary layer activation for all tracers
    387    ALLOCATE(conv_flg(nbtr)); conv_flg(1:nbtr) = 1
    388    ALLOCATE( pbl_flg(nbtr));  pbl_flg(1:nbtr) = 1
     494   IF(.NOT.ALLOCATED(conv_flg)) ALLOCATE(conv_flg(nbtr)); conv_flg(1:nbtr) = 1
     495   IF(.NOT.ALLOCATED( pbl_flg)) ALLOCATE( pbl_flg(nbtr));  pbl_flg(1:nbtr) = 1
    389496
    390497   !--- Note: nqtottr can differ from nbtr when nmom/=0
     
    394501
    395502   !=== DISPLAY THE RESULTS
     503   IF(.NOT.is_master) RETURN
    396504   CALL msg('nqo    = '//TRIM(int2str(nqo)),    modname)
    397505   CALL msg('nbtr   = '//TRIM(int2str(nbtr)),   modname)
     
    405513#endif
    406514   t => tracers
    407    CALL msg('Information stored in infotrac :', modname)
    408 
    409    IF(dispTable('isssssssssiiiiiiiii', ['iq  ', 'name', 'lNam', 'g0Nm', 'prnt', 'type', 'phas', 'comp',    &
    410                 'isPh', 'isAd', 'iadv', 'iGen', 'iqPr', 'nqDe', 'nqCh', 'iGrp', 'iNam', 'iZon', 'iPha'],   &
    411       cat(t%name, t%longName, t%gen0Name, t%parent, t%type, t%phase, t%component, bool2str(t%isInPhysics), &
    412                                                                                   bool2str(t%isAdvected)), &
     515   CALL msg('Information stored in '//TRIM(modname)//': ', modname)
     516   IF(dispTable('isssssssiiiiiiiii', ['iq  ', 'name', 'lNam', 'g0Nm', 'prnt', 'type', 'phas', 'comp',      &
     517                              'iAdv', 'iGen', 'iqPr', 'nqDe', 'nqCh', 'iGrp', 'iNam', 'iZon', 'iPha'],     &
     518      cat(t%name, t%longName, t%gen0Name, t%parent, t%type, t%phase, t%component),                         &
    413519      cat([(iq, iq=1, nqtot)], t%iadv, t%iGeneration, t%iqParent, t%nqDescen, t%nqChildren, t%iso_iGroup,  &
    414520                  t%iso_iName, t%iso_iZone, t%iso_iPhase), nColMax=maxTableWidth, nHead=2, sub=modname))   &
    415521      CALL abort_gcm(modname, "problem with the tracers table content", 1)
    416    IF(niso > 0) THEN
    417       CALL msg('Where, for isotopes family "'//TRIM(isotope%parent)//'":', modname)
    418       CALL msg('  isoKeys%name = '//strStack(isoKeys%name), modname)
    419       CALL msg('  isoName = '//strStack(isoName),      modname)
    420       CALL msg('  isoZone = '//strStack(isoZone),      modname)
    421       CALL msg('  isoPhas = '//TRIM(isoPhas),          modname)
     522   CALL msg('No isotopes identified.', modname, nbIso == 0)
     523   IF(nbIso == 0) RETURN
     524   DO it = 1, nbIso
     525      IF(isoSelect(it, .TRUE.)) CALL abort_gcm(modname, 'Problem when selecting isotopes class', 1)
     526      CALL msg('For isotopes family "'//TRIM(isoFamilies(it))//'":', modname)
     527      CALL msg('  isoName = '//strStack(isotope%trac),  modname)
     528      CALL msg('  isoZone = '//strStack(isotope%zone),  modname)
     529      CALL msg('  isoPhas = '//    TRIM(isotope%phase), modname)
     530   END DO
     531   IF(isoSelect('H2O', .TRUE.)) THEN
     532      IF(isoSelect(1,  .TRUE.)) CALL abort_gcm(modname, 'Problem when selecting isotopes class', 1)
    422533   ELSE
    423       CALL msg('No isotopes identified.', modname)
     534      iH2O = ixIso
    424535   END IF
    425    CALL msg('end', modname)
     536   IF(ALLOCATED(isotope%keys(ixIso)%key)) &
     537     CALL msg('  isoKeys('//TRIM(int2str(ixIso))//') = '//TRIM(strStack(isotope%keys(ixIso)%key)), modname)
    426538
    427539END SUBROUTINE init_infotrac
    428540
     541!==============================================================================================================================
     542LOGICAL FUNCTION isoSelectByName(iClass, lVerbose) RESULT(lerr)
     543   IMPLICIT NONE
     544   CHARACTER(LEN=*),  INTENT(IN) :: iClass
     545   LOGICAL, OPTIONAL, INTENT(IN) :: lVerbose
     546   INTEGER :: iIso
     547   LOGICAL :: lV
     548   lV = .FALSE.; IF(PRESENT(lVerbose)) lV = lVerbose
     549   iIso = strIdx(isotopes(:)%name, iClass)
     550   lerr = iIso == 0
     551   IF(lerr) THEN
     552      niso = 0; ntiso = 0; nzone = 0; nphas = 0; isoCheck=.FALSE.
     553      CALL msg('no isotope family named "'//TRIM(iClass)//'"', ll=lV)
     554      RETURN
     555   END IF
     556   lerr = isoSelectByIndex(iIso, lV)
     557END FUNCTION isoSelectByName
     558!==============================================================================================================================
     559LOGICAL FUNCTION isoSelectByIndex(iIso, lVerbose) RESULT(lerr)
     560   IMPLICIT NONE
     561   INTEGER,           INTENT(IN) :: iIso
     562   LOGICAL, OPTIONAL, INTENT(IN) :: lVerbose
     563   LOGICAL :: lV
     564   lV = .FALSE.;  IF(PRESENT(lVerbose)) lV = lVerbose
     565   lerr = .FALSE.
     566   IF(iIso == ixIso) RETURN                                          !--- Nothing to do if the index is already OK
     567   lerr = iIso<=0 .OR. iIso>SIZE(isotopes)
     568   CALL msg('Inconsistent isotopes family index '//TRIM(int2str(iIso))//': should be > 0 and <= '&
     569          //TRIM(int2str(SIZE(isotopes)))//'"', ll = lerr .AND. lV)
     570   IF(lerr) RETURN
     571   ixIso = iIso                                                      !--- Update currently selected family index
     572   isotope  => isotopes(ixIso)                                       !--- Select corresponding component
     573   isoKeys  => isotope%keys;     niso     = isotope%niso
     574   isoName  => isotope%trac;     ntiso    = isotope%ntiso
     575   isoZone  => isotope%zone;     nzone    = isotope%nzone
     576   isoPhas  => isotope%phase;    nphas    = isotope%nphas
     577   itZonIso => isotope%itZonIso; isoCheck = isotope%check
     578   iqIsoPha => isotope%iqIsoPha
     579END FUNCTION isoSelectByIndex
     580!==============================================================================================================================
     581
    429582END MODULE infotrac
  • LMDZ6/trunk/libf/dyn3d_common/iso_verif_dyn.F

    r4325 r5183  
    6464        function iso_verif_aberrant_nostop
    6565     :           (x,iso,q,err_msg)
    66         USE infotrac, ONLY: isoName, getKey
     66#ifdef CPP_IOIPSL
     67        USE IOIPSL, ONLY: getin
     68#else
     69        USE ioipsl_getincom, ONLY: getin
     70#endif
     71        USE iso_params_mod, ONLY: tnat_HDO
    6772        implicit none
    6873       
     
    7479        ! locals
    7580        real qmin,deltaD
    76         real deltaDmax,deltaDmin,tnat
     81        real deltaDmax,deltaDmin
    7782        parameter (qmin=1e-11)
    7883        parameter (deltaDmax=200.0,deltaDmin=-999.9)
     84        LOGICAL       :: ltnat1
     85        LOGICAL, SAVE :: lFirst=.TRUE.
     86        REAL,    SAVE :: tnat
    7987
    8088        ! output
    8189        integer iso_verif_aberrant_nostop
    8290
     91        IF(lFirst) THEN
     92           ltnat1 = .TRUE.; CALL getin('tnateq1', ltnat1)
     93           tnat = tnat_HDO; IF(ltnat1) tnat = 1.0
     94           lFirst = .FALSE.
     95        END IF
    8396        iso_verif_aberrant_nostop=0
    8497
    8598        ! verifier que HDO est raisonable
    8699         if (q.gt.qmin) then
    87              IF(getKey('tnat', tnat, isoName(iso))) THEN
    88                   err_msg = 'Missing isotopic parameter "tnat"'
    89                   iso_verif_aberrant_nostop=1
    90                   RETURN
    91              END IF
    92100             deltaD=(x/q/tnat-1)*1000
    93101             if ((deltaD.gt.deltaDmax).or.(deltaD.lt.deltaDmin)) then
  • LMDZ6/trunk/libf/dyn3dmem/check_isotopes_loc.F90

    r4984 r5183  
    33   USE strings_mod, ONLY: maxlen, msg, strIdx, strStack, int2str, real2str
    44   USE infotrac,    ONLY: nqtot, niso, nphas, isotope, isoCheck, iqIsoPha, isoSelect, &
    5                           ntiso, iH2O, nzone, tracers, isoName,  itZonIso, getKey
     5                          ntiso, iH2O, nzone, tracers, isoName,  itZonIso
     6   USE iso_params_mod, ONLY: tnat_H216O, tnat_H217O, tnat_H218O, tnat_HDO, tnat_HTO
     7#ifdef CPP_IOIPSL
     8   USE ioipsl,          ONLY: getin
     9#else
     10   USE ioipsl_getincom, ONLY: getin
     11#endif
    612   IMPLICIT NONE
    713   include "dimensions.h"
     
    2127                      deltaDmin =-999.0, &
    2228                      ridicule  = 1e-12
    23    INTEGER, SAVE :: iso_eau, iso_HDO, iso_O18, & !--- OpenMP shared variables
    24                              iso_O17, iso_HTO
     29   INTEGER, SAVE :: iso_eau, iso_HDO, iso_O18, iso_O17, iso_HTO
     30!$OMP THREADPRIVATE(iso_eau, iso_HDO, iso_O18, iso_O17, iso_HTO)
     31   LOGICAL       :: ltnat1
    2532   LOGICAL, SAVE :: first=.TRUE.
    26    LOGICAL, PARAMETER :: tnat1=.TRUE.
    2733!$OMP THREADPRIVATE(first)
    2834
     
    3238   IF(niso == 0)        RETURN                   !--- No isotopes => finished
    3339   IF(first) THEN
    34 !$OMP MASTER
    35       iso_eau = strIdx(isoName,'H216O')
    36       iso_HDO = strIdx(isoName,'HDO')
    37       iso_O18 = strIdx(isoName,'H218O')
    38       iso_O17 = strIdx(isoName,'H217O')
    39       iso_HTO = strIdx(isoName,'HTO')
    40       if (tnat1) then
    41               tnat(:)=1.0
    42       else
    43          IF(getKey('tnat', tnat)) CALL abort_gcm(modname, 'missing isotopic parameter', 1)
    44       endif
    45 !$OMP END MASTER
    46 !$OMP BARRIER
     40      ltnat1 = .TRUE.; CALL getin('tnateq1', ltnat1)
     41      iso_eau = strIdx(isoName,'H216O'); IF(iso_eau /= 0) tnat(iso_eau) = tnat_H216O
     42      iso_O17 = strIdx(isoName,'H217O'); IF(iso_O17 /= 0) tnat(iso_O17) = tnat_H217O
     43      iso_O18 = strIdx(isoName,'H218O'); IF(iso_O18 /= 0) tnat(iso_O18) = tnat_H218O
     44      iso_HDO = strIdx(isoName,'HDO');   IF(iso_HDO /= 0) tnat(iso_HDO) = tnat_HDO
     45      iso_HTO = strIdx(isoName,'HTO');   IF(iso_HTO /= 0) tnat(iso_HTO) = tnat_HTO
     46      IF(ltnat1) tnat(:) = 1.0
    4747      first = .FALSE.
    4848   END IF
  • LMDZ6/trunk/libf/dyn3dmem/dynetat0_loc.F90

    r5084 r5183  
    77!-------------------------------------------------------------------------------
    88  USE parallel_lmdz
    9   USE infotrac,    ONLY: nqtot, tracers, niso, iqIsoPha, iH2O, isoName
     9  USE infotrac,    ONLY: nqtot, tracers, niso, iqIsoPha, iH2O, isoName, &
     10                         new2oldH2O, newHNO3, oldHNO3
    1011  USE strings_mod, ONLY: maxlen, msg, strStack, real2str, int2str, strIdx
    1112  USE netcdf,      ONLY: NF90_OPEN,  NF90_NOWRITE, NF90_INQUIRE_DIMENSION, NF90_INQ_VARID, &
    1213                         NF90_CLOSE, NF90_GET_VAR, NF90_INQUIRE_VARIABLE,  NF90_NoErr
    13   USE readTracFiles_mod, ONLY: new2oldH2O, newHNO3, oldHNO3, getKey
    1414  USE control_mod, ONLY: planet_type
    1515  USE assert_eq_m, ONLY: assert_eq
     
    2020  USE temps_mod, ONLY: annee_ref, day_ini, day_ref, itau_dyn, start_time
    2121  USE ener_mod, ONLY: etot0,ptot0,ztot0,stot0,ang0
     22#ifdef CPP_IOIPSL
     23  USE IOIPSL,   ONLY: getin
     24#else
     25  USE ioipsl_getincom, ONLY: getin
     26#endif
     27  USE iso_params_mod   ! tnat_* and alpha_ideal_*
    2228
    2329  IMPLICIT NONE
     
    4753  REAL,             ALLOCATABLE :: ucov_glo(:,:),    q_glo(:,:), phis_glo(:)
    4854  REAL,             ALLOCATABLE :: teta_glo(:,:)
    49   LOGICAL :: lSkip, ll
    50   LOGICAL,PARAMETER :: tnat1=.TRUE.
     55  LOGICAL :: lSkip, ll, ltnat1
    5156!-------------------------------------------------------------------------------
    5257  modname="dynetat0_loc"
     
    158163  ll = NF90_INQ_VARID(fID, 'HNO3tot', vID) /= NF90_NoErr                                 !--- DETECT OLD REPRO start.nc FILE
    159164#endif
     165  ltnat1 = .TRUE.; CALL getin('tnateq1', ltnat1)
    160166  DO iq=1,nqtot
    161167    var = tracers(iq)%name
     
    173179    !--------------------------------------------------------------------------------------------------------------------------
    174180    ELSE IF(NF90_INQ_VARID(fID, oldVar, vID) == NF90_NoErr) THEN                         !=== TRY WITH ALTERNATE NAME
    175       CALL msg('Tracer <'//TRIM(var)//'> is missing => initialized to <'//TRIM(oldVar)//'>', modname)
     181      CALL msg('Missing tracer <'//TRIM(var)//'> => initialized to <'//TRIM(oldVar)//'>', modname)
    176182      CALL get_var2(oldVar, q_glo); q(ijb_u:ije_u,:,iq)=q_glo(ijb_u:ije_u,:)
    177183    !--------------------------------------------------------------------------------------------------------------------------
     
    181187      iqParent = tracers(iq)%iqParent
    182188      IF(tracers(iq)%iso_iZone == 0) THEN
    183          if (tnat1) then
    184                  tnat=1.0
    185                  alpha_ideal=1.0
    186                  write(*,*) 'attention dans dynetat0: les alpha_ideal sont a 1'
    187          else
    188           IF(getKey('tnat', tnat, isoName(iName)) .OR. getKey('alpha', alpha_ideal, isoName(iName))) &
    189             CALL abort_gcm(TRIM(modname), 'missing isotopic parameters', 1)
    190          endif
    191          CALL msg('Tracer <'//TRIM(var)//'> is missing => initialized with a simplified Rayleigh distillation law.', modname)
     189         IF(ltnat1) THEN
     190            tnat = 1.0
     191            alpha_ideal = 1.0
     192            CALL msg(' !!!  Beware: alpha_ideal put to 1  !!!', modname)
     193         ELSE
     194            SELECT CASE(isoName(iName))
     195              CASE('H216O'); tnat = tnat_H216O; alpha_ideal = alpha_ideal_H216O
     196              CASE('H217O'); tnat = tnat_H217O; alpha_ideal = alpha_ideal_H217O
     197              CASE('H218O'); tnat = tnat_H218O; alpha_ideal = alpha_ideal_H218O
     198              CASE('HDO');   tnat = tnat_HDO;   alpha_ideal = alpha_ideal_HDO
     199              CASE('HTO');   tnat = tnat_HTO;   alpha_ideal = alpha_ideal_HTO
     200              CASE DEFAULT; CALL abort_gcm(TRIM(modname),'unknown isotope "'//TRIM(isoName(iName))//'" ; check tracer.def file',1)
     201            END SELECT
     202         END IF
     203         CALL msg('Missing tracer <'//TRIM(var)//'> => initialized with a simplified Rayleigh distillation law.', modname)
    192204         q(ijb_u:ije_u,:,iq) = q(ijb_u:ije_u,:,iqParent)*tnat*(q(ijb_u:ije_u,:,iqParent)/30.e-3)**(alpha_ideal-1.)
    193205         ! Camille 9 mars 2023: point de vigilence: initialisation incohérente
    194206         ! avec celle de xt_ancien dans la physiq.
    195207      ELSE
    196          CALL msg('Tracer <'//TRIM(var)//'> is missing => initialized to its parent isotope concentration.', modname)
     208         CALL msg('Missing tracer <'//TRIM(var)//'> => initialized to its parent isotope concentration.', modname)
    197209         ! Camille 9 mars 2023: attention!! seuls les tags qui correspondent à
    198210         ! izone=izone_init (définie dans isotrac_mod) sont initialisés comme
     
    208220    !--------------------------------------------------------------------------------------------------------------------------
    209221    ELSE                                                                                 !=== MISSING: SET TO 0
    210       CALL msg('Tracer <'//TRIM(var)//'> is missing => initialized to zero', modname)
     222      CALL msg('missing tracer <'//TRIM(var)//'> => initialized to zero', modname)
    211223      q(ijb_u:ije_u,:,iq)=0.
    212224    !--------------------------------------------------------------------------------------------------------------------------
  • LMDZ6/trunk/libf/dyn3dmem/iniacademic_loc.F90

    r5084 r5183  
    55
    66  USE filtreg_mod, ONLY: inifilr
    7   USE infotrac,    ONLY: nqtot, niso, iqIsoPha, tracers, getKey, isoName
     7  USE infotrac,    ONLY: nqtot, niso, iqIsoPha, tracers, addPhase, isoName
    88  USE control_mod, ONLY: day_step,planet_type
    99  use exner_hyb_m, only: exner_hyb
     
    2222  USE temps_mod, ONLY: annee_ref, day_ini, day_ref
    2323  USE ener_mod, ONLY: etot0,ptot0,ztot0,stot0,ang0
    24   USE readTracFiles_mod, ONLY: addPhase
    2524  use netcdf, only : NF90_NOWRITE,NF90_OPEN,NF90_NOERR,NF90_INQ_VARID
    2625  use netcdf, only : NF90_CLOSE, NF90_GET_VAR
     26  USE iso_params_mod   ! tnat_* and alpha_ideal_*
    2727
    2828
     
    8585
    8686  REAL zdtvr, tnat, alpha_ideal
    87   LOGICAL,PARAMETER :: tnat1=.true.
     87  LOGICAL :: ltnat1
    8888 
    8989  character(len=*),parameter :: modname="iniacademic"
     
    311311        ! bulk initialization of tracers
    312312        if (planet_type=="earth") then
     313           ltnat1 = .TRUE.; CALL getin('tnateq1', ltnat1)
    313314           ! Earth: first two tracers will be water
    314315           do iq=1,nqtot
     
    324325              iqParent = tracers(iq)%iqParent
    325326              IF(tracers(iq)%iso_iZone == 0) THEN
    326                  if (tnat1) then
    327                          tnat=1.0
    328                          alpha_ideal=1.0
    329                          write(*,*) 'Attention dans iniacademic: alpha_ideal=1'
    330                  else
    331                     IF(getKey('tnat', tnat, isoName(iName)) .OR. getKey('alpha', alpha_ideal, isoName(iName))) &
    332                     CALL abort_gcm(TRIM(modname), 'missing isotopic parameters', 1)
    333                  endif
     327                 IF(ltnat1) THEN
     328                    tnat = 1.0
     329                    alpha_ideal = 1.0
     330                    WRITE(lunout, *) 'In '//TRIM(modname)//': !!!  Beware: alpha_ideal put to 1  !!!'
     331                 ELSE
     332                    SELECT CASE(isoName(iName))
     333                      CASE('H216O'); tnat = tnat_H216O; alpha_ideal = alpha_ideal_H216O
     334                      CASE('H217O'); tnat = tnat_H217O; alpha_ideal = alpha_ideal_H217O
     335                      CASE('H218O'); tnat = tnat_H218O; alpha_ideal = alpha_ideal_H218O
     336                      CASE('HDO');   tnat = tnat_HDO;   alpha_ideal = alpha_ideal_HDO
     337                      CASE('HTO');   tnat = tnat_HTO;   alpha_ideal = alpha_ideal_HTO
     338                      CASE DEFAULT
     339                         CALL abort_gcm(TRIM(modname),'unknown isotope "'//TRIM(isoName(iName))//'" ; check tracer.def file',1)
     340                    END SELECT
     341                 END IF
    334342                 q(ijb_u:ije_u,:,iq) = q(ijb_u:ije_u,:,iqParent)*tnat*(q(ijb_u:ije_u,:,iqParent)/30.e-3)**(alpha_ideal-1.)
    335343              ELSE !IF(tracers(iq)%iso_iZone == 0) THEN
  • LMDZ6/trunk/libf/dyn3dmem/qminimum_loc.F

    r5001 r5183  
    44      SUBROUTINE qminimum_loc( q,nqtot,deltap )
    55      USE parallel_lmdz
    6       USE infotrac, ONLY: niso, ntiso, iqIsoPha, tracers,
     6      USE infotrac, ONLY: niso, ntiso, iqIsoPha, tracers, addPhase,
    77     &                    isoCheck, min_qParent
    88      USE strings_mod, ONLY: strIdx
    9       USE readTracFiles_mod, ONLY: addPhase
    109      IMPLICIT none
    1110c
  • LMDZ6/trunk/libf/dynphy_lonlat/calfis.F

    r4464 r5183  
    2929c    Auteur :  P. Le Van, F. Hourdin
    3030c   .........
    31       USE infotrac, ONLY: nqtot, tracers
     31      USE infotrac_phy, ONLY: nqtot, tracers
    3232      USE control_mod, ONLY: planet_type, nsplit_phys
    3333#ifdef CPP_PHYS
  • LMDZ6/trunk/libf/dynphy_lonlat/calfis_loc.F

    r5084 r5183  
    4747      USE Times
    4848#endif
    49       USE infotrac, ONLY: nqtot, tracers
     49      USE infotrac_phy, ONLY: nqtot, tracers
    5050      USE control_mod, ONLY: planet_type, nsplit_phys
    5151#ifdef CPP_PHYS
  • LMDZ6/trunk/libf/misc/readTracFiles_mod.f90

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

    r5003 r5183  
    33MODULE infotrac_phy
    44
    5    USE       strings_mod, ONLY: msg, fmsg, maxlen, cat, dispTable, int2str, bool2str, strStack, strParse, strIdx
    6    USE readTracFiles_mod, ONLY: trac_type, readTracersFiles, tracers, setGeneration, itZonIso, nzone, tran0, isoZone, &
    7         delPhase, niso, getKey, isot_type, processIsotopes,  isotope, maxTableWidth, iqIsoPha, nphas, ixIso, isoPhas, &
    8         addPhase, iH2O, addKey, isoSelect, testTracersFiles, isoKeys, indexUpdate,  iqWIsoPha, nbIso, ntiso, isoName, isoCheck
     5   USE       strings_mod, ONLY: msg, maxlen, cat, dispTable, int2str, bool2str, strStack, strParse, strCount, strIdx
     6   USE readTracFiles_mod, ONLY: readTracersFiles, maxTableWidth,  tisot=>isot_type, addPhase, addKey, iH2O, &
     7        indexUpdate, keys_type, testTracersFiles, processIsotopes, trac=>tracers,   delPhase, getKey, tran0
     8   USE readTracFiles_mod, ONLY: new2oldH2O
     9
    910   IMPLICIT NONE
    1011
     
    1617   PUBLIC :: nqtot,   nbtr,   nqo,   nqCO2,   nqtottr      !--- Main dimensions
    1718   PUBLIC :: conv_flg, pbl_flg                             !--- Convection & boundary layer activation keys
    18 #ifdef CPP_StratAer
     19   PUBLIC :: new2oldH2O                                    !--- For backwards compatibility in phyetat0
     20   PUBLIC :: addPhase, delPhase                            !--- Add/remove the phase from the name of a tracer
     21#if defined CPP_StratAer || defined REPROBUS
    1922   PUBLIC :: nbtr_bin, nbtr_sulgas                         !--- Number of aerosols bins and sulfur gases for StratAer model
    2023   PUBLIC :: id_OCS_strat, id_SO2_strat, id_H2SO4_strat, id_BIN01_strat, id_TEST_strat
    2124#endif
    2225
    23    !=== FOR WATER
    24    PUBLIC :: ivap, iliq, isol
    2526   !=== FOR ISOTOPES: General
    2627   PUBLIC :: isot_type, nbIso                              !--- Derived type, full isotopes families database + nb of families
    27    PUBLIC :: isoSelect, ixIso                              !--- Isotopes family selection tool + selected family index
     28   PUBLIC :: isoSelect, ixIso, isoFamilies                 !--- Isotopes families selection tool + selected index + list
    2829   !=== FOR ISOTOPES: Specific to water
    29    PUBLIC :: iH2O                                          !--- H2O isotopes class index
     30   PUBLIC :: iH2O                                          !--- Value of "ixIso" for "H2O" isotopes class
     31   PUBLIC :: ivap, iliq, isol
    3032   !=== FOR ISOTOPES: Depending on the selected isotopes family
    31    PUBLIC :: isotope, isoKeys                              !--- Selected isotopes database + associated keys (cf. getKey)
    32    PUBLIC :: isoName, isoZone, isoPhas                     !--- Isotopes and tagging zones names, phases
    33    PUBLIC :: niso,    nzone,   nphas,   ntiso              !---  " " numbers + isotopes & tagging tracers number
    34    PUBLIC :: itZonIso                                      !--- idx "it" (in "isoName(1:niso)") = function(tagging idx, isotope idx)
    35    PUBLIC :: iqIsoPha                                      !--- idx "iq" (in "qx") = function(isotope idx, phase idx) + aliases
    36    PUBLIC :: iqWIsoPha                                      !--- Same as iqIsoPha but with normal water phases
    37 
     33   PUBLIC :: isotope                                       !--- Selected isotopes database (argument of getKey)
     34   PUBLIC :: isoKeys, isoName, isoZone, isoPhas            !--- Isotopes keys & names, tagging zones names, phases
     35   PUBLIC ::    niso,   ntiso,   nzone,   nphas            !--- Number of   "   "
     36   PUBLIC :: itZonIso                                      !--- index "it" in "isoName(1:niso)" = f(tagging idx, isotope idx)
     37   PUBLIC :: iqIsoPha                                      !--- index "iq" in "qx"              = f(isotope idx,   phase idx)
     38   PUBLIC :: iqWIsoPha                                     !--- Same as iqIsoPha but with normal water phases
    3839   PUBLIC :: isoCheck                                      !--- Run isotopes checking routines
    3940   !=== FOR BOTH TRACERS AND ISOTOPES
     
    4344!  |--------------------+-----------------------+-----------------+---------------+----------------------------|
    4445!  | water in different |    water tagging      |  water isotopes | other tracers | additional tracers moments |
    45 !  | phases: H2O_[gls|      isotopes         |                 |               |  for higher order schemes  |
     46!  | phases: H2O_[glsrb]|      isotopes         |                 |               |  for higher order schemes  |
    4647!  |--------------------+-----------------------+-----------------+---------------+----------------------------|
    4748!  |                    |                       |                 |               |                            |
     
    5758!  |-----------------------------------------------------------------------------------------------------------|
    5859!  NOTES FOR THIS TABLE:
    59 !  * Used "niso", "nzone" and "ntiso" are components of "isotopes(ip)" for water (isotopes(ip)%parent == 'H2O'),
     60!  * Used "niso", "nzone" and "ntiso" are components of "isotopes(ip)" for water (isotopes(ip)%name == 'H2O'),
    6061!    since water is so far the sole tracers family, except passive CO2, removed from the main tracers table.
    6162!  * For water, "nqo" is equal to the more general field "isotopes(ip)%nphas".
    6263!  * "niso", "nzone", "ntiso", "nphas" are defined for other isotopic tracers families, if any.
     64!  * If you deal with an isotopes family other than "H2O" ("Sulf" in the example), a good practice is to keep
     65!    track of the isotopes class (of its index) before switching to it at the beginning of the dedicated code:
     66!  - first time (use selection by name and compute the corresponding index iSulf) :
     67!  i0=ixIso; IF(.NOT.isoSelect('Sulf')) CALL abort_physic("Can't select isotopes class", modname, 1); iS=ixIso
     68!  - next times (use selection by index - "iS" has been computed at first call):
     69!  i0=ixIso; IF(.NOT.isoSelect(iS))     CALL abort_physic("Can't select isotopes class", modname, 1)
     70!    and to switch back to the original category when you're done with "Sulf":
     71!            IF(.NOT.isoSelect(i0))     CALL abort_physic("Can't select isotopes class", modname, 1)
     72!    to restore the original isotopes category (before dealing with "Sulf" (most of the time "H2O").
    6373!
    6474!=== DERIVED TYPE EMBEDDING MOST OF THE TRACERS-RELATED QUANTITIES (LENGTH: nqtot)
     
    6878!  |-------------+------------------------------------------------------+-------------+------------------------+
    6979!  | name        | Name (short)                                         | tname       |                        |
     80!  | keys        | key/val pairs accessible with "getKey" routine       | /           |                        |
    7081!  | gen0Name    | Name of the 1st generation ancestor                  | /           |                        |
    7182!  | parent      | Name of the parent                                   | /           |                        |
    7283!  | longName    | Long name (with adv. scheme suffix) for outputs      | ttext       |                        |
    7384!  | type        | Type (so far: tracer or tag)                         | /           | tracer,tag             |
    74 !  | phase       | Phases list ("g"as / "l"iquid / "s"olid)             | /           | [g][l][s]              |
     85!  | phase       | Phases list ("g"as / "l"iquid / "s"olid              |             | [g|l|s|r|b]            |
     86!  |             |              "r"(cloud) / "b"lowing)                 | /           |                        |
    7587!  | component   | Name(s) of the merged/cumulated section(s)           | /           | coma-separated names   |
    7688!  | iGeneration | Generation (>=1)                                     | /           |                        |
     
    7991!  | nqDescen    | Number of the descendants   (all generations)        | nqdesc      | 1:nqtot                |
    8092!  | nqChildren  | Number of childs            (1st generation only)    | nqfils      | 1:nqtot                |
    81 !  | keys        | key/val pairs accessible with "getKey" routine       | /           |                        |
    82 !  | isAdvected  | advected tracers flag (.TRUE. if iadv >= 0)          | /           | nqtrue  .TRUE. values  |
    83 !  | isInPhysics | tracers not extracted from the main table in physics | /           | nqtottr .TRUE. values  |
     93!  | isAdvected  | Advected tracers flag (.TRUE. if iadv >= 0)          | /           | nqtrue  .TRUE. values  |
     94!  | isInPhysics | Tracers not extracted from the main table in physics | /           | nqtottr .TRUE. values  |
    8495!  | iso_iGroup  | Isotopes group index in isotopes(:)                  | /           | 1:nbIso                |
    8596!  | iso_iName   | Isotope  name  index in isotopes(iso_iGroup)%trac(:) | iso_indnum  | 1:niso                 |
     
    93104!  |  entry | length | Meaning                                          |    Former name     | Possible values |
    94105!  |-----------------+--------------------------------------------------+--------------------+-----------------+
    95 !  | parent          | Parent tracer (isotopes family name)             |                    |                 |
     106!  | name            | Name of the isotopes class (family)              |                    |                 |
    96107!  | keys   | niso   | Isotopes keys/values pairs list + number         |                    |                 |
    97108!  | trac   | ntiso  | Isotopes + tagging tracers list + number         | / | ntraciso       |                 |
    98109!  | zone   | nzone  | Geographic tagging zones   list + number         | / | ntraceurs_zone |                 |
    99 !  | phase  | nphas  | Phases                     list + number         |                    | [g][l][s], 1:3 |
     110!  | phase  | nphas  | Phases                     list + number         |                    | [g|l|s|r|b] 1:5 |
    100111!  | iqIsoPha        | Index in "qx"           = f(name(1:ntiso)),phas) | iqiso              | 1:nqtot         |
    101 !  | iqWIsoPha       | Index in "qx"           = f(name(1:ntiso)),phas) | iqiso              | 1:nqtot         |
     112!  | iqWIsoPha       | Index in "qx"       = f(name(1:ntiso+nqo)),phas) |   ?                | 1:nqtot         |
    102113!  | itZonIso        | Index in "trac(1:ntiso)"= f(zone, name(1:niso))  | index_trac         | 1:ntiso         |
    103114!  +-----------------+--------------------------------------------------+--------------------+-----------------+
    104115
     116!------------------------------------------------------------------------------------------------------------------------------
     117   TYPE :: trac_type                                            !=== TYPE FOR A SINGLE TRACER NAMED "name"
     118     CHARACTER(LEN=maxlen) :: name        = ''                  !--- Name of the tracer
     119     TYPE(keys_type)       :: keys                              !--- <key>=<val> pairs vector (general container)
     120     CHARACTER(LEN=maxlen) :: gen0Name    = ''                  !--- First generation ancestor name
     121     CHARACTER(LEN=maxlen) :: parent      = ''                  !--- Parent name
     122     CHARACTER(LEN=maxlen) :: longName    = ''                  !--- Long name (with advection scheme suffix)
     123     CHARACTER(LEN=maxlen) :: type        = 'tracer'            !--- Type  (so far: 'tracer' / 'tag')
     124     CHARACTER(LEN=maxlen) :: phase       = 'g'                 !--- Phase ('g'as / 'l'iquid / 's'olid)
     125     CHARACTER(LEN=maxlen) :: component   = ''                  !--- Coma-separated list of components (Ex: lmdz,inca)
     126     INTEGER               :: iGeneration = -1                  !--- Generation number (>=0)
     127     INTEGER               :: iqParent    = 0                   !--- Parent index
     128     INTEGER,  ALLOCATABLE :: iqDescen(:)                       !--- Descendants index (in growing generation order)
     129     INTEGER               :: nqDescen    = 0                   !--- Number of descendants (all generations)
     130     INTEGER               :: nqChildren  = 0                   !--- Number of children  (first generation)
     131     LOGICAL               :: isAdvected  = .FALSE.             !--- "true" tracers: iadv > 0.   COUNT(isAdvected )=nqtrue
     132     LOGICAL               :: isInPhysics = .TRUE.              !--- "true" tracers: in tr_seri. COUNT(isInPhysics)=nqtottr
     133     INTEGER               :: iso_iGroup  = 0                   !--- Isotopes group index in isotopes(:)
     134     INTEGER               :: iso_iName   = 0                   !--- Isotope  name  index in isotopes(iso_iGroup)%trac(:)
     135     INTEGER               :: iso_iZone   = 0                   !--- Isotope  zone  index in isotopes(iso_iGroup)%zone(:)
     136     INTEGER               :: iso_iPhase  = 0                   !--- Isotope  phase index in isotopes(iso_iGroup)%phase
     137   END TYPE trac_type
     138!------------------------------------------------------------------------------------------------------------------------------
     139  TYPE :: isot_type                                             !=== TYPE FOR THE ISOTOPES FAMILY DESCENDING ON TRACER "name"
     140    CHARACTER(LEN=maxlen)              :: name                  !--- Isotopes family name (ex: H2O)
     141    TYPE(keys_type),       ALLOCATABLE :: keys(:)               !--- Isotopes keys/values pairs list     (length: niso)
     142    LOGICAL                            :: check=.FALSE.         !--- Flag for checking routines triggering
     143    CHARACTER(LEN=maxlen), ALLOCATABLE :: trac(:)               !--- Isotopes + tagging tracers list     (length: ntiso)
     144    CHARACTER(LEN=maxlen), ALLOCATABLE :: zone(:)               !--- Geographic tagging zones names list (length: nzone)
     145    CHARACTER(LEN=maxlen)              :: phase = 'g'           !--- Phases list: [g|l|s|r|b]            (length: nphas)
     146    INTEGER                            :: niso  = 0             !--- Number of isotopes, excluding tagging tracers
     147    INTEGER                            :: ntiso = 0             !--- Number of isotopes, including tagging tracers
     148    INTEGER                            :: nzone = 0             !--- Number of geographic tagging zones
     149    INTEGER                            :: nphas = 0             !--- Number of phases
     150    INTEGER,               ALLOCATABLE :: iqIsoPha(:,:)         !--- Idx in "tracers(1:nqtot)" = f(     name(1:ntiso) ,phas)
     151    INTEGER,               ALLOCATABLE :: iqWIsoPha(:,:)        !--- Idx in "tracers(1:nqtot)" = f([H2O,name(1:ntiso)],phas)
     152    INTEGER,               ALLOCATABLE :: itZonIso(:,:)         !--- Idx in "trac(1:ntiso)"    = f(zone,name(1:niso))
     153  END TYPE isot_type
     154!------------------------------------------------------------------------------------------------------------------------------
     155  INTERFACE isoSelect; MODULE PROCEDURE isoSelectByIndex, isoSelectByName; END INTERFACE isoSelect
     156!------------------------------------------------------------------------------------------------------------------------------
     157
     158   !=== INDICES FOR WATER
     159   INTEGER, SAVE :: ivap, iliq, isol
     160!$OMP THREADPRIVATE(ivap, iliq, isol)
     161
    105162   !=== DIMENSIONS OF THE TRACERS TABLES AND OTHER SCALAR VARIABLES
    106    INTEGER,               SAVE :: nqtot,  &                     !--- Tracers nb in dynamics (incl. higher moments + H2O)
    107                                   nbtr,   &                     !--- Tracers nb in physics  (excl. higher moments + H2O)
    108                                   nqo,    &                     !--- Number of water phases
     163   INTEGER,               SAVE :: nqtot,   &                    !--- Tracers nb in dynamics (incl. higher moments + H2O)
     164                                  nbtr,    &                    !--- Tracers nb in physics  (excl. higher moments + H2O)
     165                                  nqo,     &                    !--- Number of water phases
    109166                                  nqtottr, &                    !--- Number of tracers passed to phytrac (TO BE DELETED ?)
    110167                                  nqCO2                         !--- Number of tracers of CO2  (ThL)
     
    112169!$OMP THREADPRIVATE(nqtot, nbtr, nqo, nqtottr, nqCO2, type_trac)
    113170
    114    !=== INDICES OF WATER
    115    INTEGER,               SAVE :: ivap,iliq,isol ! Indices for vap, liq and ice
    116 !$OMP THREADPRIVATE(ivap,iliq,isol)
     171   !=== NUMBER AND LIST OF DEFINED ISOTOPES FAMILIES
     172   INTEGER,               SAVE              :: nbIso            !--- Number of defined isotopes classes
     173   CHARACTER(LEN=maxlen), SAVE, ALLOCATABLE :: isoFamilies(:)   !--- Generation 0 tracer name for each isotopes family (nbIso)
     174!$OMP THREADPRIVATE(isoFamilies)
     175
     176   !=== QUANTITIES RELATED TO THE CURRENTLY SELECTED ISOTOPES CLASS (USUALLY H2O)
     177   TYPE(isot_type),       SAVE, POINTER :: isotope              !--- Selected isotopes database (=isotopes(ixIso))
     178   TYPE(keys_type),       SAVE, POINTER :: isoKeys(:)           !--- Database to get isotopes keys using "getKey"       (niso)
     179   CHARACTER(LEN=maxlen), SAVE, POINTER :: isoName(:),      &   !--- Isotopes list including tagging tracers, no phase (ntiso)
     180                                           isoZone(:),      &   !--- Geographic tagging zones list                     (nzone)
     181                                           isoPhas              !--- Used phases names ([g|l|s|r|b])                   (nphas)
     182   INTEGER,               SAVE, POINTER :: itZonIso(:,:),   &   !--- Idx "it" in isoName(1:niso) = f(tagging idx, isotope idx)
     183                                           iqIsoPha(:,:),   &   !--- Idx "iq" in qx              = f(isotope idx,   phase idx)
     184                                           iqWIsoPha(:,:)       !--- Idx "iq" in qx = f([parent trac,isotope idx],  phase idx)
     185   INTEGER,               SAVE          :: ixIso,           &   !--- Idx in "isoFamilies" of currently selectd class
     186                                           niso,            &   !--- Number of isotopes
     187                                           ntiso,           &   !--- Number of isotopes + tagging tracers
     188                                           nzone,           &   !--- Number of tagging zones
     189                                           nphas                !--- Number of phases
     190   LOGICAL,               SAVE          :: isoCheck             !--- Isotopes checking routines triggering flag
     191!$OMP THREADPRIVATE(isotope, isoKeys, isoName, isoZone, isoPhas, itZonIso, iqIsoPha, iqWIsoPha, niso, ntiso, nzone, nphas, isoCheck)
    117192
    118193   !=== VARIABLES FOR INCA
    119    INTEGER,               SAVE, ALLOCATABLE :: conv_flg(:), &   !--- Convection     activation ; needed for INCA        (nbtr)
    120                                                 pbl_flg(:)      !--- Boundary layer activation ; needed for INCA        (nbtr)
     194   INTEGER, DIMENSION(:), SAVE, ALLOCATABLE :: &
     195                    conv_flg, pbl_flg                           !--- Convection / boundary layer activation (nbtr)
    121196!$OMP THREADPRIVATE(conv_flg, pbl_flg)
    122197
    123 #ifdef CPP_StratAer
     198   !=== TRACERS/ISOTOPES DESCRIPTORS: EFFECTIVE STORAGE (LOCAL DERIVED TYPES)
     199   TYPE(trac_type), SAVE, ALLOCATABLE, TARGET ::  tracers(:)
     200   TYPE(isot_type), SAVE, ALLOCATABLE, TARGET :: isotopes(:)
     201!$OMP THREADPRIVATE(tracers, isotopes)
     202
     203#if defined CPP_StratAer || defined REPROBUS
    124204  !=== SPECIFIC TO STRATOSPHERIC AEROSOLS (CK/OB)
    125205  INTEGER, SAVE ::  nbtr_bin, nbtr_sulgas         !--- number of aerosols bins and sulfur gases for StratAer model
     
    133213SUBROUTINE init_infotrac_phy
    134214   USE ioipsl_getin_p_mod, ONLY: getin_p
     215   USE mod_phys_lmdz_para, ONLY: is_master, is_omp_master
    135216#ifdef REPROBUS
    136217   USE CHEM_REP, ONLY: Init_chem_rep_trac
     
    161242!------------------------------------------------------------------------------------------------------------------------------
    162243! Local variables
    163    INTEGER, ALLOCATABLE :: hadv(:), vadv(:)                          !--- Horizontal/vertical transport scheme number
     244   INTEGER, ALLOCATABLE :: hadv(:), vadv(:), itmp(:)                 !--- Horizontal/vertical transport scheme number
    164245#ifdef INCA
    165246   INTEGER, ALLOCATABLE :: had (:), hadv_inca(:), conv_flg_inca(:), &!--- Variables specific to INCA
     
    173254   CHARACTER(LEN=2)      ::   suff(9)                                !--- Suffixes for schemes of order 3 or 4 (Prather)
    174255   CHARACTER(LEN=3)      :: descrq(30)                               !--- Advection scheme description tags
    175    CHARACTER(LEN=maxlen) :: msg1, texp, ttp                          !--- String for messages and expanded tracers type
     256   CHARACTER(LEN=maxlen) :: msg1, texp, ttp, ky                      !--- Strings for messages and expanded tracers type
    176257   INTEGER :: fType                                                  !--- Tracers description file type ; 0: none
    177258                                                                     !--- 1/2/3: "traceur.def"/"tracer.def"/"tracer_*.def"
    178259   INTEGER :: nqtrue                                                 !--- Tracers nb from tracer.def (no higher order moments)
    179260   INTEGER :: iad                                                    !--- Advection scheme number
    180    INTEGER :: iq, jq, nt, im, nm, k                                 !--- Indexes and temporary variables
     261   INTEGER :: iq, jq, it, nt, im, nm                                 !--- Indexes and temporary variables
    181262   LOGICAL :: lerr, lInit
     263   TYPE(keys_type), ALLOCATABLE, TARGET :: tra(:)                    !--- Tracers  descriptor as in readTracFiles_mod
     264   TYPE(tisot),     ALLOCATABLE         :: iso(:)                    !--- Isotopes descriptor as in readTracFiles_mod
    182265   TYPE(trac_type), ALLOCATABLE, TARGET :: ttr(:)
    183    TYPE(trac_type), POINTER             :: t1, t(:)
    184    CHARACTER(LEN=maxlen),   ALLOCATABLE :: types_trac(:)  !--- Keyword for tracers type(s), parsed version
    185    
     266   TYPE(trac_type), POINTER             :: t(:), t1
     267   TYPE(keys_type), POINTER             :: k(:)
     268   CHARACTER(LEN=maxlen),   ALLOCATABLE :: types_trac(:)             !--- Keywords for tracers type(s), parsed version
    186269   CHARACTER(LEN=*), PARAMETER :: modname="init_infotrac_phy"
    187270!------------------------------------------------------------------------------------------------------------------------------
     
    195278
    196279   CALL getin_p('type_trac',type_trac)
    197 
    198    lerr=strParse(type_trac, '|', types_trac, n=nt)
    199    IF (nt .GT. 1) THEN
    200       IF (nt .GT. 2) CALL abort_physic(modname, 'you need to modify type_trac, this version is not supported by lmdz', 1)
    201       IF (nt .EQ. 2) type_trac=types_trac(2)
    202    ENDIF
    203 
    204    
    205    CALL msg('type_trac = "'//TRIM(type_trac)//'"', modname)
    206    lInit = .NOT.ALLOCATED(tracers)
     280   CALL msg('type_trac = "'//TRIM(type_trac)//'"', modname, is_master)
     281   IF(strCount(type_trac, '|', nt)) CALL abort_physic(modname, 'Could''nt parse the "type_trac" string with delimiter "|"', 1)
     282   IF(nt >= 3) CALL abort_physic(modname, 'you need to modify type_trac, this version is not supported by lmdz', 1)
     283   IF(strParse(type_trac, '|', types_trac, n=nt)) CALL abort_physic(modname, "couldn't parse "//'"type_trac"', 1)
     284   IF(nt == 2) type_trac = types_trac(2) ! TO BE DELETED SOON
     285
     286   lInit = .NOT.ALLOCATED(trac)
    207287
    208288!##############################################################################################################################
    209    IF(lInit) THEN                                                    !=== SKIPED IF ALREADY DONE IN dyn3d_common/infotrac  ####
     289   IF(lInit .AND. is_master) THEN                                    !=== SKIPED IF ALREADY DONE
    210290!##############################################################################################################################
    211291   !--- MESSAGE ABOUT THE CHOSEN CONFIGURATION
     
    240320!##############################################################################################################################
    241321
    242    nqCO2 = COUNT( [type_trac == 'inco', type_trac == 'co2i'] )
    243 
    244 !==============================================================================================================================
    245 ! 1) Get the numbers of: true (first order only) tracers "nqtrue", water tracers "nqo" (vapor/liquid/solid)
    246 !==============================================================================================================================
    247    texp = type_trac                                                  !=== EXPANDED VERSION OF "type_trac", WITH "|" SEPARATOR
     322!==============================================================================================================================
     323! 0) DETERMINE THE TYPE OF THE INPUT TRACERS DESCRIPTION FILE AND READ IT ; TRANSFER THE NEEDED QUANTITIES TO LOCAL "tracers".
     324!==============================================================================================================================
     325   texp = type_trac                                                            !=== EXPANDED (WITH "|" SEPARATOR) "type_trac"
    248326   IF(texp == 'inco') texp = 'co2i|inca'
    249327   IF(texp /= 'lmdz') texp = 'lmdz|'//TRIM(texp)
    250 
    251    !=== DETERMINE THE TYPE OF THE INPUT TRACERS DESCRIPTION FILE
    252    IF(testTracersFiles(modname, texp, fType, lInit)) CALL abort_physic(modname, 'problem with tracers file(s)',1)
    253 
     328   IF(testTracersFiles(modname, texp, fType, lInit.AND.is_master)) CALL abort_physic(modname, 'problem with tracers file(s)',1)
    254329   ttp = type_trac; IF(fType /= 1) ttp = texp
     330   !---------------------------------------------------------------------------------------------------------------------------
     331   IF(fType == 0) CALL abort_physic(modname, 'Missing "traceur.def", "tracer.def" or "tracer_<keyword>.def tracers file.',1)
     332   !---------------------------------------------------------------------------------------------------------------------------
     333   IF(fType == 1 .AND. ANY(['inca', 'inco'] == type_trac)) &                   !=== FOUND OLD STYLE INCA "traceur.def"
     334      CALL abort_physic(modname, 'retro-compatibility with old-style INCA traceur.def files has been disabled.', 1)
     335   !---------------------------------------------------------------------------------------------------------------------------
    255336
    256337!##############################################################################################################################
    257    IF(lInit) THEN
    258       IF(readTracersFiles(ttp, lRepr=type_trac=='repr')) CALL abort_physic(modname, 'problem with tracers file(s)',1)
     338   IF(lInit .AND. is_omp_master) THEN
     339      IF(readTracersFiles(ttp, tra, type_trac == 'repr')) CALL abort_physic(modname, 'problem with tracers file(s)',1)
    259340   ELSE
    260       CALL msg('No tracers description file(s) reading needed: already done in the dynamics', modname)
    261    END IF
     341      tra = trac
     342   END IF
     343   CALL msg('No tracers description file(s) reading needed: already done', modname, .NOT.lInit.AND.is_master)
    262344!##############################################################################################################################
    263345
    264    !---------------------------------------------------------------------------------------------------------------------------
    265    IF(fType == 0) CALL abort_physic(modname, 'Missing tracers file: "traceur.def", "tracer.def" or "tracer_<keyword>.def file.',1)
    266    !---------------------------------------------------------------------------------------------------------------------------
    267    IF(fType == 1 .AND. ANY(['inca','inco']==type_trac) .AND. lInit) THEN  !=== FOUND OLD STYLE INCA "traceur.def"
    268    !---------------------------------------------------------------------------------------------------------------------------
     346   !--- POPULATE SOME EXPLICIT (ACCESSIBLE THROUGH "%") KEYS OF THE LOCAL TRACERS DESCRIPTION DERIVED TYPE
     347   !    To be defined: iqParent, iq/nqDescen, nqChildren (in indexUpdate), longName, iso_i*, isAdvected, isInPhysics (later)
     348   ALLOCATE(tracers(SIZE(tra)))
     349   DO iq = 1, SIZE(tra); t1 => tracers(iq)
     350      t1%keys = tra(iq)
     351      msg1 = '" for tracer nr. '//TRIM(int2str(iq))
     352      ky='name       '; IF(getKey(ky, t1%name,        iq, tra)) CALL abort_physic(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1)
     353      msg1 = '" for "'//TRIM(t1%name)//'"'
     354      ky='gen0Name   '; IF(getKey(ky, t1%gen0Name,    iq, tra)) CALL abort_physic(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1)
     355      ky='parent     '; IF(getKey(ky, t1%parent,      iq, tra)) CALL abort_physic(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1)
     356      ky='type       '; IF(getKey(ky, t1%type,        iq, tra)) CALL abort_physic(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1)
     357      ky='phase      '; IF(getKey(ky, t1%phase,       iq, tra)) CALL abort_physic(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1)
     358      ky='component  '; IF(getKey(ky, t1%component,   iq, tra)) CALL abort_physic(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1)
     359      ky='iGeneration'; IF(getKey(ky, t1%iGeneration, iq, tra)) CALL abort_physic(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1)
     360   END DO
     361
     362!==============================================================================================================================
     363! 1) Get various numbers: "nqtrue" (first order only tracers), "nqo" (water phases), 'nbtr' (tracers passed to physics), etc.
     364!==============================================================================================================================
     365   nqtrue = SIZE(tracers)                                                                               !--- "true" tracers
     366   nqo    =      COUNT(tracers(:)%component == 'lmdz' .AND. delPhase(tracers(:)%name)     == 'H2O')     !--- Water phases
     367   nbtr = nqtrue-COUNT(tracers(:)%component == 'lmdz' .AND. delPhase(tracers(:)%gen0Name) == 'H2O')     !--- Passed to phytrac
     368   nqCO2  =      COUNT( [type_trac == 'inco', type_trac == 'co2i'] )
    269369#ifdef INCA
    270       nqo = SIZE(tracers) - nqCO2
    271       CALL Init_chem_inca_trac(nqINCA)                               !--- Get nqINCA from INCA
    272       nbtr = nqINCA + nqCO2                                          !--- Number of tracers passed to phytrac
    273       nqtrue = nbtr + nqo                                            !--- Total number of "true" tracers
    274       IF(ALL([2,3] /= nqo)) CALL abort_physic(modname, 'Only 2 or 3 water phases allowed ; found nqo='//TRIM(int2str(nqo)), 1)
    275       ALLOCATE(hadv(nqtrue), hadv_inca(nqINCA), conv_flg_inca(nqINCA), solsym_inca(nqINCA))
    276       ALLOCATE(vadv(nqtrue), vadv_inca(nqINCA),  pbl_flg_inca(nqINCA))
    277       CALL init_transport(solsym_inca, conv_flg_inca, pbl_flg_inca, hadv_inca, vadv_inca)
    278       ALLOCATE(ttr(nqtrue))
    279       ttr(1:nqo+nqCO2)                  = tracers
    280       ttr(1    :      nqo   )%component = 'lmdz'
    281       ttr(1+nqo:nqCO2+nqo   )%component = 'co2i'
    282       ttr(1+nqo+nqCO2:nqtrue)%component = 'inca'
    283       ttr(1+nqo      :nqtrue)%name      = [('CO2     ', k=1, nqCO2), solsym_inca]
    284       ttr(1+nqo+nqCO2:nqtrue)%parent    = tran0
    285       ttr(1+nqo+nqCO2:nqtrue)%phase     = 'g'
    286       lerr = getKey('hadv', had, ky=tracers(:)%keys)
    287       lerr = getKey('vadv', vad, ky=tracers(:)%keys)
    288       hadv(1:nqo+nqCO2) = had(:); hadv(1+nqo+nqCO2:nqtrue) = hadv_inca
    289       vadv(1:nqo+nqCO2) = vad(:); vadv(1+nqo+nqCO2:nqtrue) = vadv_inca
    290       CALL MOVE_ALLOC(FROM=ttr, TO=tracers)
    291       DO iq = 1, nqtrue
    292          t1 => tracers(iq)
    293          CALL addKey('name',      t1%name,      t1%keys)
    294          CALL addKey('component', t1%component, t1%keys)
    295          CALL addKey('parent',    t1%parent,    t1%keys)
    296          CALL addKey('phase',     t1%phase,     t1%keys)
    297       END DO
    298       IF(setGeneration(tracers)) CALL abort_physic(modname,'See below',1) !- SET FIELDS %iGeneration, %gen0Name
    299       DEALLOCATE(had, hadv_inca, vad, vadv_inca, conv_flg_inca, pbl_flg_inca, solsym_inca)
    300 #endif
    301    !---------------------------------------------------------------------------------------------------------------------------
    302    ELSE                                                              !=== OTHER CASES (OLD OR NEW FORMAT, NO INCA MODULE)
    303    !---------------------------------------------------------------------------------------------------------------------------
    304       nqo    =        COUNT(delPhase(tracers(:)%name)     == 'H2O' &
    305                                .AND. tracers(:)%component == 'lmdz') !--- Number of water phases
    306       nqtrue = SIZE(tracers)                                         !--- Total number of "true" tracers
    307       nbtr   = nqtrue-COUNT(delPhase(tracers(:)%gen0Name) == 'H2O' &
    308                                .AND. tracers(:)%component == 'lmdz') !--- Number of tracers passed to phytrac
    309 #ifdef INCA
    310       nqINCA = COUNT(tracers(:)%component == 'inca')
    311 #endif
    312       lerr = getKey('hadv', hadv, ky=tracers(:)%keys)
    313       lerr = getKey('vadv', vadv, ky=tracers(:)%keys)
    314    !---------------------------------------------------------------------------------------------------------------------------
    315    END IF
    316    !---------------------------------------------------------------------------------------------------------------------------
    317 
    318    !--- Transfert the number of tracers to Reprobus
     370   nqINCA =      COUNT(tracers(:)%component == 'inca')
     371#endif
    319372#ifdef REPROBUS
    320    CALL Init_chem_rep_trac(nbtr, nqo, tracers(:)%name)
    321 #endif
    322 
    323 !##############################################################################################################################
    324    IF(lInit) THEN                                                    !=== SKIPED IF ALREADY DONE IN dyn3d_common/infotrac  ####
    325 !##############################################################################################################################
     373   CALL Init_chem_rep_trac(nbtr, nqo, tracers(:)%name)                         !--- Transfert the number of tracers to Reprobus
     374#endif
    326375
    327376!==============================================================================================================================
    328377! 2) Calculate nqtot, number of tracers needed (greater if advection schemes 20 or 30 have been chosen).
    329378!==============================================================================================================================
     379   IF(getKey('hadv', hadv, ky=tra)) CALL abort_physic(modname, 'missing key "hadv"', 1)
     380   IF(getKey('vadv', vadv, ky=tra)) CALL abort_physic(modname, 'missing key "vadv"', 1)
    330381   DO iq = 1, nqtrue
    331382      IF( hadv(iq)<20 .OR. (ANY(hadv(iq)==[20,30]) .AND. hadv(iq)==vadv(iq)) ) CYCLE
     
    348399!==============================================================================================================================
    349400   ALLOCATE(ttr(nqtot))
    350    jq = nqtrue+1; tracers(:)%iadv = -1
     401   jq = nqtrue+1
    351402   DO iq = 1, nqtrue
    352403      t1 => tracers(iq)
     
    359410      IF(iad == -1) CALL abort_physic(modname, msg1, 1)
    360411
    361       !--- SET FIELDS %longName, %isAdvected, %isInPhysics
     412      !--- SET FIELDS longName, isAdvected, isInPhysics
    362413      t1%longName   = t1%name; IF(iad > 0) t1%longName=TRIM(t1%name)//descrq(iad)
    363414      t1%isAdvected = iad >= 0
    364       t1%isInPhysics= delPhase(t1%gen0Name) /= 'H2O' &
    365                           .OR. t1%component /= 'lmdz' !=== OTHER EXCEPTIONS TO BE ADDED: CO2i, SURSATURATED WATER CLOUD...
     415      t1%isInPhysics= delPhase(t1%gen0Name) /= 'H2O' .OR. t1%component /= 'lmdz' !=== MORE EXCEPTIONS ? CO2i, SURSAT CLOUD H2O
    366416      ttr(iq)       = t1
    367417
     
    372422      IF(nm == 0) CYCLE                                              !--- No higher moments
    373423      ttr(jq+1:jq+nm)             = t1
    374       ttr(jq+1:jq+nm)%name        = [(TRIM(t1%name)    //'-'//TRIM(suff(im)), im=1, nm) ]
    375       ttr(jq+1:jq+nm)%parent      = [(TRIM(t1%parent)  //'-'//TRIM(suff(im)), im=1, nm) ]
    376       ttr(jq+1:jq+nm)%longName    = [(TRIM(t1%longName)//'-'//TRIM(suff(im)), im=1, nm) ]
    377       ttr(jq+1:jq+nm)%isAdvected  = [(.FALSE., im=1, nm) ]
     424      ttr(jq+1:jq+nm)%name        = [ (TRIM(t1%name)    //'-'//TRIM(suff(im)), im=1, nm) ]
     425      ttr(jq+1:jq+nm)%gen0Name    = [ (TRIM(t1%name)    //'-'//TRIM(suff(im)), im=1, nm) ]
     426      ttr(jq+1:jq+nm)%parent      = [ (TRIM(t1%parent)  //'-'//TRIM(suff(im)), im=1, nm) ]
     427      ttr(jq+1:jq+nm)%longName    = [ (TRIM(t1%longName)//'-'//TRIM(suff(im)), im=1, nm) ]
     428      ttr(jq+1:jq+nm)%isAdvected  = [ (.FALSE., im=1, nm) ]
     429      ttr(jq+1:jq+nm)%isInPhysics = [ (.FALSE., im=1, nm) ]
    378430      jq = jq + nm
    379431   END DO
     
    381433   CALL MOVE_ALLOC(FROM=ttr, TO=tracers)
    382434
    383    !--- SET FIELDS %iqParent, %nqChildren, %iGeneration, %iqDescen, %nqDescen
    384    IF(indexUpdate(tracers)) CALL abort_gcm(modname, 'problem when processing isotopes parameters', 1)
    385 
    386 !##############################################################################################################################
    387    END IF
    388 !##############################################################################################################################
    389 
    390 !##############################################################################################################################
    391    IF(.NOT.lInit) THEN
    392 !##############################################################################################################################
    393      nqtot = SIZE(tracers)
    394 !##############################################################################################################################
    395    ELSE
    396 !##############################################################################################################################
    397 
    398    !=== READ PHYSICAL PARAMETERS FOR ISOTOPES
    399    niso = 0; nzone = 0; nphas = nqo; ntiso = 0; isoCheck = .FALSE.
    400    IF(processIsotopes()) CALL abort_physic(modname, 'Problem when processing isotopes parameters', 1)
    401 
    402 !##############################################################################################################################
    403    END IF
    404 !##############################################################################################################################
     435   !--- SET FIELDS iqParent, iqDescen, nqDescen, nqChildren
     436   IF(indexUpdate(tracers%keys)) CALL abort_physic(modname, 'problem with tracers indices update', 1)
     437   k => tracers(:)%keys
     438   DO iq = 1, SIZE(tracers); t1 => tracers(iq); msg1 = '" for "'//TRIM(t1%name)//'"'
     439      ky='iqParent  '; IF(getKey(ky, t1%iqParent,   iq, k)) CALL abort_physic(modname, 'missing key "'//TRIM(ky)//TRIM(msg1), 1)
     440      ky='iqDescen  '; IF(getKey(ky, t1%iqDescen,   iq, k)) CALL abort_physic(modname, 'missing key "'//TRIM(ky)//TRIM(msg1), 1)
     441      ky='nqDescen  '; IF(getKey(ky, t1%nqDescen,   iq, k)) CALL abort_physic(modname, 'missing key "'//TRIM(ky)//TRIM(msg1), 1)
     442      ky='nqChildren'; IF(getKey(ky, t1%nqChildren, iq, k)) CALL abort_physic(modname, 'missing key "'//TRIM(ky)//TRIM(msg1), 1)
     443   END DO
     444
     445   !=== DETERMINE ISOTOPES RELATED PARAMETERS ; DEFINE THE EXPLICIT KEYS iso_i*
     446   IF(processIsotopes(tracers%keys, iso)) CALL abort_physic(modname, 'problem while processing isotopes parameters', 1)
     447
     448   !--- POPULATE SOME EXPLICIT (ACCESSIBLE THROUGH "%") KEYS OF THE LOCAL ISOTOPES DESCRIPTION DERIVED TYPE
     449   nbIso = SIZE(iso)
     450   ALLOCATE(isotopes(nbIso))
     451   IF(nbIso /= 0) THEN
     452      k => tracers(:)%keys
     453      IF(getKey('iso_iGroup', itmp, ky=k)) CALL abort_physic(modname, 'missing key "iso_iGroup"', 1); tracers%iso_iGroup = itmp
     454      IF(getKey('iso_iName',  itmp, ky=k)) CALL abort_physic(modname, 'missing key "iso_iName"',  1); tracers%iso_iName  = itmp
     455      IF(getKey('iso_iZone',  itmp, ky=k)) CALL abort_physic(modname, 'missing key "iso_iZone"',  1); tracers%iso_iZone  = itmp
     456      IF(getKey('iso_iPhas',  itmp, ky=k)) CALL abort_physic(modname, 'missing key "iso_iPhas"',  1); tracers%iso_iPhase = itmp
     457      isotopes(:)%name  = iso(:)%name                           !--- Isotopes family name (ex: H2O)
     458      isotopes(:)%phase = iso(:)%phase                          !--- Phases list: [g][l][s]              (length: nphas)
     459      isotopes(:)%niso  = iso(:)%niso                           !--- Number of isotopes, excluding tagging tracers
     460      isotopes(:)%ntiso = iso(:)%ntiso                          !--- Number of isotopes, including tagging tracers
     461      isotopes(:)%nzone = iso(:)%nzone                          !--- Number of geographic tagging zones
     462      isotopes(:)%nphas = iso(:)%nphas                          !--- Number of phases
     463      isotopes(:)%check = .FALSE.                               !--- Flag for checking routines triggering
     464      CALL getin_p('ok_iso_verif', isotopes(:)%check)
     465      DO it = 1, nbIso
     466         isotopes(it)%keys     = iso(it)%keys                   !--- Isotopes keys/values pairs list     (length: niso)
     467         isotopes(it)%trac     = iso(it)%trac                   !--- Isotopes + tagging tracers list     (length: ntiso)
     468         isotopes(it)%zone     = iso(it)%zone                   !--- Geographic tagging zones names list (length: nzone)
     469         isotopes(it)%iqIsoPha = iso(it)%iqIsoPha(:,:)          !--- Idx in "tracers(1:nqtot)" = f(name(1:ntiso)),phas)
     470         isotopes(it)%iqWIsoPha= iso(it)%iqWIsoPha(:,:)         !--- Idx in "tracers(1:nqtot)" = f([trPrnt,name(1:ntiso)],phas)
     471         isotopes(it)%itZonIso = iso(it)%itZonIso(:,:)          !--- Idx in "tracers(1:ntiso)" = f(  zone,name(1:niso))
     472      END DO
     473      IF(isoSelect(1, .TRUE.)) CALL abort_physic(modname, "Can't select the first isotopes family", 1)
     474      IF(.NOT.isoSelect('H2O', .TRUE.)) iH2O = ixIso
     475   END IF
     476   isoFamilies = isotopes(:)%name
     477
    405478   !--- Convection / boundary layer activation for all tracers
    406    IF (.NOT.ALLOCATED(conv_flg)) ALLOCATE(conv_flg(nbtr)); conv_flg(1:nbtr) = 1
    407    IF (.NOT.ALLOCATED(pbl_flg)) ALLOCATE( pbl_flg(nbtr));  pbl_flg(1:nbtr) = 1
     479   IF(.NOT.ALLOCATED(conv_flg)) ALLOCATE(conv_flg(nbtr)); conv_flg(1:nbtr) = 1
     480   IF(.NOT.ALLOCATED( pbl_flg)) ALLOCATE( pbl_flg(nbtr));  pbl_flg(1:nbtr) = 1
    408481
    409482   !--- Note: nqtottr can differ from nbtr when nmom/=0
     
    413486
    414487   !=== DISPLAY THE RESULTS
     488   IF(.NOT.is_master) RETURN
    415489   CALL msg('nqo    = '//TRIM(int2str(nqo)),    modname)
    416490   CALL msg('nbtr   = '//TRIM(int2str(nbtr)),   modname)
     
    424498#endif
    425499   t => tracers
    426    CALL msg('Information stored in infotrac_phy :', modname)
    427    IF(dispTable('issssssssiiiiiiii', ['iq  ', 'name', 'lNam', 'g0Nm', 'prnt', 'type', 'phas', 'comp',      &
    428                               'isPh', 'iGen', 'iqPr', 'nqDe', 'nqCh', 'iGrp', 'iNam', 'iZon', 'iPha'],     &
    429       cat(t%name, t%longName, t%gen0Name, t%parent, t%type, t%phase, t%component, bool2str(t%isInPhysics)),&
     500   CALL msg('Information stored in '//TRIM(modname)//': ', modname)
     501   IF(dispTable('isssssssssiiiiiiii', ['iq  ', 'name', 'lNam', 'g0Nm', 'prnt', 'type', 'phas', 'comp',     &
     502                       'isPh', 'isAd', 'iGen', 'iqPr', 'nqDe', 'nqCh', 'iGrp', 'iNam', 'iZon', 'iPha'],    &
     503      cat(t%name, t%longName, t%gen0Name, t%parent, t%type, t%phase, t%component,                          &
     504                                                         bool2str(t%isInPhysics), bool2str(t%isAdvected)), &
    430505      cat([(iq, iq=1, nqtot)], t%iGeneration, t%iqParent, t%nqDescen, t%nqChildren, t%iso_iGroup,          &
    431506                  t%iso_iName, t%iso_iZone, t%iso_iPhase), nColMax=maxTableWidth, nHead=2, sub=modname))   &
    432507      CALL abort_physic(modname, "problem with the tracers table content", 1)
    433    IF(niso > 0) THEN
    434       CALL msg('Where, for isotopes family "'//TRIM(isotope%parent)//'":', modname)
    435       CALL msg('  isoKeys%name = '//strStack(isoKeys%name), modname)
    436       CALL msg('  isoName = '//strStack(isoName),      modname)
    437       CALL msg('  isoZone = '//strStack(isoZone),      modname)
    438       CALL msg('  isoPhas = '//TRIM(isoPhas),          modname)
    439    ELSE
    440       CALL msg('No isotopes identified.', modname)
    441    END IF
    442 
    443 #ifdef ISOVERIF
    444    CALL msg('iso_iName = '//strStack(int2str(PACK(tracers(:)%iso_iName, MASK=tracers(:)%iso_iGroup==iH2O))), modname)
    445 #endif
    446508#ifdef CPP_StratAer
    447509   IF (type_trac == 'coag') THEN
     
    463525   END IF
    464526#endif
    465    CALL msg('end', modname)
     527   CALL msg('No isotopes identified.', modname, nbIso == 0)
     528   IF(nbIso == 0) RETURN
     529   DO it = 1, nbIso
     530      IF(isoSelect(it, .TRUE.)) CALL abort_physic(modname, 'Problem when selecting isotopes class', 1)
     531      CALL msg('For isotopes family "'//TRIM(isoFamilies(it))//'":', modname)
     532      CALL msg('  isoName = '//strStack(isotope%trac),  modname)
     533      CALL msg('  isoZone = '//strStack(isotope%zone),  modname)
     534      CALL msg('  isoPhas = '//    TRIM(isotope%phase), modname)
     535   END DO
     536   IF(isoSelect('H2O', .TRUE.)) THEN
     537      IF(isoSelect(1,  .TRUE.)) CALL abort_physic(modname, 'Problem when selecting isotopes class', 1)
     538   ELSE
     539      iH2O = ixIso
     540   END IF
     541   IF(ALLOCATED(isotope%keys(ixIso)%key)) &
     542      CALL msg('  isoKeys('//TRIM(int2str(ixIso))//') = '//TRIM(strStack(isotope%keys(ixIso)%key)), modname)
     543#ifdef ISOVERIF
     544   CALL msg('iso_iName(H2O) = '//TRIM(strStack(int2str(PACK(tracers%iso_iName, MASK=tracers%iso_iGroup==iH2O)))),modname)
     545#endif
    466546
    467547END SUBROUTINE init_infotrac_phy
    468548
     549!==============================================================================================================================
     550LOGICAL FUNCTION isoSelectByName(iClass, lVerbose) RESULT(lerr)
     551   IMPLICIT NONE
     552   CHARACTER(LEN=*),  INTENT(IN) :: iClass
     553   LOGICAL, OPTIONAL, INTENT(IN) :: lVerbose
     554   INTEGER :: iIso
     555   LOGICAL :: lV
     556   lV = .FALSE.; IF(PRESENT(lVerbose)) lV = lVerbose
     557   iIso = strIdx(isotopes(:)%name, iClass)
     558   lerr = iIso == 0
     559   IF(lerr) THEN
     560      niso = 0; ntiso = 0; nzone = 0; nphas = 0; isoCheck=.FALSE.
     561      CALL msg('no isotope family named "'//TRIM(iClass)//'"', ll=lV)
     562      RETURN
     563   END IF
     564   lerr = isoSelectByIndex(iIso, lV)
     565END FUNCTION isoSelectByName
     566!==============================================================================================================================
     567LOGICAL FUNCTION isoSelectByIndex(iIso, lVerbose) RESULT(lerr)
     568   IMPLICIT NONE
     569   INTEGER,           INTENT(IN) :: iIso
     570   LOGICAL, OPTIONAL, INTENT(IN) :: lVerbose
     571   LOGICAL :: lV
     572   lV = .FALSE.;  IF(PRESENT(lVerbose)) lV = lVerbose
     573   lerr = .FALSE.
     574   IF(iIso == ixIso) RETURN                                          !--- Nothing to do if the index is already OK
     575   lerr = iIso<=0 .OR. iIso>SIZE(isotopes)
     576   CALL msg('Inconsistent isotopes family index '//TRIM(int2str(iIso))//': should be > 0 and <= '&
     577          //TRIM(int2str(SIZE(isotopes)))//'"', ll = lerr .AND. lV)
     578   IF(lerr) RETURN
     579   ixIso = iIso                                                      !--- Update currently selected family index
     580   isotope  => isotopes(ixIso)                                       !--- Select corresponding component
     581   isoKeys  => isotope%keys;     niso     = isotope%niso
     582   isoName  => isotope%trac;     ntiso    = isotope%ntiso
     583   isoZone  => isotope%zone;     nzone    = isotope%nzone
     584   isoPhas  => isotope%phase;    nphas    = isotope%nphas
     585   itZonIso => isotope%itZonIso; isoCheck = isotope%check
     586   iqIsoPha => isotope%iqIsoPha
     587   iqWIsoPha=> isotope%iqWIsoPha
     588END FUNCTION isoSelectByIndex
     589!==============================================================================================================================
     590
    469591END MODULE infotrac_phy
  • LMDZ6/trunk/libf/phylmd/phyetat0_mod.F90

    r5084 r5183  
    3232  USE geometry_mod,     ONLY: longitude_deg, latitude_deg
    3333  USE iostart,          ONLY: close_startphy, get_field, get_var, open_startphy
    34   USE infotrac_phy,     ONLY: nqtot, nbtr, type_trac, tracers
    35   USE readTracFiles_mod,ONLY: maxlen, new2oldH2O
     34  USE infotrac_phy,     ONLY: nqtot, nbtr, type_trac, tracers, new2oldH2O
     35  USE strings_mod,      ONLY: maxlen
    3636  USE traclmdz_mod,     ONLY: traclmdz_from_restart
    3737  USE carbon_cycle_mod, ONLY: carbon_cycle_init, carbon_cycle_cpl, carbon_cycle_tr, carbon_cycle_rad, co2_send, RCO2_glo
  • LMDZ6/trunk/libf/phylmd/physiq_mod.F90

    r5169 r5183  
    3939    USE ioipsl_getin_p_mod, ONLY : getin_p
    4040    USE indice_sol_mod
    41     USE infotrac_phy, ONLY: nqtot, nbtr, nqo, tracers, type_trac
    42     USE readTracFiles_mod, ONLY: addPhase
     41    USE infotrac_phy, ONLY: nqtot, nbtr, nqo, tracers, type_trac, addPhase
    4342    USE strings_mod,  ONLY: strIdx
    4443    USE iophy
  • LMDZ6/trunk/libf/phylmdiso/isotopes_mod.F90

    r4982 r5183  
    44MODULE isotopes_mod
    55   USE strings_mod,  ONLY: msg, real2str, int2str, bool2str, maxlen, strIdx, strStack
    6    USE infotrac_phy, ONLY: isoName
     6   USE infotrac_phy, ONLY: isoName, isoSelect, niso, ntiso, nbIso, isoFamilies
     7   USE iso_params_mod
    78   IMPLICIT NONE
    89   INTERFACE get_in; MODULE PROCEDURE getinp_s, getinp_i, getinp_r, getinp_l;  END INTERFACE get_in
     
    1112  !--- Contains all isotopic variables + their initialization
    1213  !--- Isotopes-specific routines are in isotopes_routines_mod to avoid circular dependencies with isotopes_verif_mod.
     14
     15   !--- Negligible lower thresholds: no need to check for absurd values under these lower limits
     16   REAL, PARAMETER :: &
     17      ridicule      = 1e-12,              & ! For mixing ratios
     18      ridicule_rain = 1e-8,               & ! For rain fluxes (rain, zrfl...) in kg/s <-> 1e-3 mm/day
     19      ridicule_evap = ridicule_rain*1e-2, & ! For evaporations                in kg/s <-> 1e-3 mm/day
     20      ridicule_qsol = ridicule_rain,      & ! For qsol                        in kg <-> 1e-8 kg
     21      ridicule_snow = ridicule_qsol         ! For snow                        in kg <-> 1e-8 kg
     22   REAL, PARAMETER :: expb_max = 30.0
     23
     24   !--- Fractionation coefficients for H217O
     25   REAL, PARAMETER :: fac_coeff_eq17_liq = 0.529,    &
     26                      fac_coeff_eq17_ice = 0.529
     27
     28   !--- H218O reference
     29   REAL, PARAMETER :: fac_enrichoce18 = 0.0005,  alpha_liq_sol_O18 = 1.00291,                    &
     30                      talph1_O18 = 1137.,        talps1_O18 = 11.839,     tkcin0_O18 = 0.006,    &
     31                      talph2_O18 = -0.4156,      talps2_O18 = -0.028244,  tkcin1_O18 = 0.000285, &
     32                      talph3_O18 = -2.0667E-3,  tdifrel_O18 = 1./0.9723,  tkcin2_O18 = 0.00082
     33
     34   !--- Parameters that do not depend on the nature of water isotopes:
     35   REAL, PARAMETER :: pxtmelt = 273.15           !--- temperature at which ice formation starts
     36   REAL, PARAMETER :: pxtice  = 273.15 -  10.0   !--- temperature at which all condensate is ice:
     37   REAL, PARAMETER :: pxtmin  = 273.15 - 120.0   !--- computation done only under -120°C
     38   REAL, PARAMETER :: pxtmax  = 273.15 +  60.0   !--- computation done only  over  +60°C
     39   REAL, PARAMETER :: tdifexp = 0.58             !--- a constant for alpha_eff for equilibrium below cloud base:
     40   REAL, PARAMETER :: tv0cin  = 7.0              !--- wind threshold (m/s) for smooth/rough regime (Merlivat and Jouzel 1979)
     41   REAL, PARAMETER :: musi    = 1.0              !--- facteurs lambda et mu dans Si=musi-lambda*T
     42   REAL, PARAMETER :: Kd      = 2.5e-9    ! m2/s !--- diffusion in soil
     43   REAL, PARAMETER :: rh_cste_surf_cond = 0.6    !--- cste_surf_cond case: rhs and/or Ts set to constants
     44   REAL, PARAMETER :: T_cste_surf_cond = 288.0
    1345
    1446   !--- Isotopes indices (in [1,niso] ; non-existing => 0 index)
     
    89121   !--- Vectors of length "niso"
    90122   REAL, ALLOCATABLE, DIMENSION(:), SAVE :: &
    91                     tnat, toce, tcorr, tdifrel
    92 !$OMP THREADPRIVATE(tnat, toce, tcorr, tdifrel)
     123                    alpha, tnat, toce, tcorr, tdifrel
     124!$OMP THREADPRIVATE(alpha, tnat, toce, tcorr, tdifrel)
    93125   REAL, ALLOCATABLE, DIMENSION(:), SAVE :: &
    94126                    talph1, talph2, talph3, talps1, talps2
     
    100132                    alpha_liq_sol, Rdefault, Rmethox
    101133!$OMP THREADPRIVATE(alpha_liq_sol, Rdefault, Rmethox)
    102 !   REAL, SAVE ::    fac_coeff_eq17_liq, fac_coeff_eq17_ice
    103 !!$OMP THREADPRIVATE(fac_coeff_eq17_liq, fac_coeff_eq17_ice)
    104 
    105    !--- H2[18]O reference
    106    REAL, PARAMETER :: fac_enrichoce18=0.0005
    107    REAL, PARAMETER :: alpha_liq_sol_O18=1.00291
    108    REAL, PARAMETER :: talph1_O18=1137.
    109    REAL, PARAMETER :: talph2_O18=-0.4156
    110    REAL, PARAMETER :: talph3_O18=-2.0667E-3
    111    REAL, PARAMETER :: talps1_O18=11.839
    112    REAL, PARAMETER :: talps2_O18=-0.028244
    113    REAL, PARAMETER :: tdifrel_O18=1./0.9723
    114    REAL, PARAMETER :: tkcin0_O18=0.006
    115    REAL, PARAMETER :: tkcin1_O18=0.000285
    116    REAL, PARAMETER :: tkcin2_O18=0.00082
    117    REAL, PARAMETER :: fac_coeff_eq17_liq=0.529
    118    REAL, PARAMETER :: fac_coeff_eq17_ice=0.529
    119 
    120    !---- Parameters that do not depend on the nature of water isotopes:
    121    REAL, PARAMETER :: pxtmelt = 273.15 ! temperature at which ice formation starts
    122    REAL, PARAMETER :: pxtice  = 273.15-10.0 ! -- temperature at which all condensate is ice:
    123    REAL, PARAMETER :: pxtmin = 273.15 - 120.0   ! On ne calcule qu'au dessus de -120°C
    124    REAL, PARAMETER :: pxtmax = 273.15 +  60.0   ! On ne calcule qu'au dessus de +60°C
    125    REAL, PARAMETER :: tdifexp = 0.58 ! -- a constant for alpha_eff for equilibrium below cloud base:
    126    REAL, PARAMETER :: tv0cin  = 7.0 ! wind threshold (m/s) for smooth/rough regime (Merlivat and Jouzel 1979)
    127    REAL, PARAMETER :: musi=1.0  ! facteurs lambda et mu dans Si=musi-lambda*T
    128    REAL, PARAMETER :: Kd=2.5e-9 ! m2/s ! diffusion dans le sol
    129    REAL, PARAMETER :: rh_cste_surf_cond = 0.6 ! cas où cste_surf_cond: on met rhs ou/et Ts cste pour voir
    130    REAL, PARAMETER :: T_cste_surf_cond = 288.0
    131 
    132 
    133    !--- Negligible lower thresholds: no need to check for absurd values under these lower limits
    134    REAL, PARAMETER :: &
    135       ridicule      = 1e-12,              & ! For mixing ratios
    136       ridicule_rain = 1e-8,               & ! For rain fluxes (rain, zrfl...) in kg/s <-> 1e-3 mm/day
    137       ridicule_evap = ridicule_rain*1e-2, & ! For evaporations                in kg/s <-> 1e-3 mm/day
    138       ridicule_qsol = ridicule_rain,      & ! For qsol                        in kg <-> 1e-8 kg
    139       ridicule_snow = ridicule_qsol         ! For snow                        in kg <-> 1e-8 kg
    140    REAL, PARAMETER :: expb_max = 30.0
    141134
    142135   !--- Specific to HTO:
     
    155148
    156149SUBROUTINE iso_init()
    157    USE infotrac_phy,       ONLY: ntiso, niso, getKey
    158     USE strings_mod,       ONLY: maxlen
    159150   IMPLICIT NONE
    160151
    161152   !=== Local variables:
    162    INTEGER :: ixt
    163 
     153   INTEGER :: ixt, ii, is
     154   LOGICAL :: ltnat1
     155   CHARACTER(LEN=maxlen) :: modname, sxt
    164156 
    165157   !--- For H2[17]O
     
    170162   LOGICAL, PARAMETER ::   ok_nocinsat = .FALSE. ! if T: no sursaturation effect for ice
    171163   LOGICAL, PARAMETER :: Rdefault_smow = .FALSE. ! if T: Rdefault=smow; if F: nul
    172    LOGICAL, PARAMETER :: tnat1 = .TRUE. ! If T: all tnats are 1.
    173164
    174165   !--- For [3]H
    175166   INTEGER :: iessai
    176 
    177    CHARACTER(LEN=maxlen) :: modname, sxt
    178167
    179168   modname = 'iso_init'
     
    187176   CALL msg('64: niso = '//TRIM(int2str(niso)), modname)
    188177
    189    !--- Init de ntracisoOR: on ecrasera en cas de traceurs de tagging isotopiques
    190    !                     (nzone>0) si complications avec ORCHIDEE
    191    ntracisoOR = ntiso 
    192 
    193    !--- Type of water isotopes:
    194    iso_eau = strIdx(isoName, 'H216O'); CALL msg('iso_eau='//int2str(iso_eau), modname)
    195    iso_HDO = strIdx(isoName, 'HDO');   CALL msg('iso_HDO='//int2str(iso_HDO), modname)
    196    iso_O18 = strIdx(isoName, 'H218O'); CALL msg('iso_O18='//int2str(iso_O18), modname)
    197    iso_O17 = strIdx(isoName, 'H217O'); CALL msg('iso_O17='//int2str(iso_O17), modname)
    198    iso_HTO = strIdx(isoName, 'HTO');   CALL msg('iso_HTO='//int2str(iso_HTO), modname)
    199 
    200    !--- Initialiaation: reading the isotopic parameters.
    201    CALL get_in('lambda',     lambda_sursat, 0.004)
    202    CALL get_in('thumxt1',    thumxt1,       0.75*1.2)
    203    CALL get_in('ntot',       ntot,          20,  .FALSE.)
    204    CALL get_in('h_land_ice', h_land_ice,    20., .FALSE.)
    205    CALL get_in('P_veg',      P_veg,         1.0, .FALSE.)
    206    CALL get_in('bidouille_anti_divergence', bidouille_anti_divergence, .FALSE.)
    207    CALL get_in('essai_convergence',         essai_convergence,         .FALSE.)
    208    CALL get_in('initialisation_iso',        initialisation_iso,        0)
    209 
    210 !  IF(nzone>0 .AND. initialisation_iso==0) &
    211 !      CALL get_in('initialisation_isotrac',initialisation_isotrac)
    212    CALL get_in('modif_sst',      modif_sst,         0)
    213    CALL get_in('deltaTtest',     deltaTtest,      0.0)     !--- For modif_sst>=1
    214    CALL get_in('deltaTtestpoles',deltaTtestpoles, 0.0)     !--- For modif_sst>=2
    215    CALL get_in( 'sstlatcrit',    sstlatcrit,     30.0)     !--- For modif_sst>=3
    216    CALL get_in('dsstlatcrit',   dsstlatcrit,      0.0)     !--- For modif_sst>=3
     178   DO ii = 1, nbIso
     179      CALL msg('Can''t select isotopes class "'//TRIM(isoFamilies(ii))//'"', modname, isoSelect(ii, lVerbose=.TRUE.))
     180
     181!==============================================================================================================================
     182      IF(isoFamilies(ii) == 'H2O') THEN
     183!==============================================================================================================================
     184         !--- Init de ntracisoOR: on ecrasera en cas de traceurs de tagging isotopiques
     185         !                     (nzone>0) si complications avec ORCHIDEE
     186         ntracisoOR = ntiso
     187
     188         !--- Type of water isotopes:
     189         iso_eau = strIdx(isoName, 'H216O'); CALL msg('iso_eau='//int2str(iso_eau), modname)
     190         iso_HDO = strIdx(isoName, 'HDO');   CALL msg('iso_HDO='//int2str(iso_HDO), modname)
     191         iso_O18 = strIdx(isoName, 'H218O'); CALL msg('iso_O18='//int2str(iso_O18), modname)
     192         iso_O17 = strIdx(isoName, 'H217O'); CALL msg('iso_O17='//int2str(iso_O17), modname)
     193         iso_HTO = strIdx(isoName, 'HTO');   CALL msg('iso_HTO='//int2str(iso_HTO), modname)
     194
     195         !--- Initialisation: reading the isotopic parameters.
     196         CALL get_in('lambda',     lambda_sursat, 0.004); IF(ok_nocinsat) lambda_sursat = 0.
     197         CALL get_in('thumxt1',    thumxt1,       0.75*1.2)
     198         CALL get_in('ntot',       ntot,          20,  .FALSE.)
     199         CALL get_in('h_land_ice', h_land_ice,    20., .FALSE.)
     200         CALL get_in('P_veg',      P_veg,         1.0, .FALSE.)
     201         CALL get_in('bidouille_anti_divergence', bidouille_anti_divergence, .FALSE.)
     202         CALL get_in('essai_convergence',         essai_convergence,         .FALSE.)
     203         CALL get_in('initialisation_iso',        initialisation_iso,        0)
     204
     205!        IF(nzone>0 .AND. initialisation_iso==0) &
     206!           CALL get_in('initialisation_isotrac',initialisation_isotrac)
     207         CALL get_in('modif_sst',      modif_sst,         0)
     208         CALL get_in('deltaTtest',     deltaTtest,      0.0)     !--- For modif_sst>=1
     209         CALL get_in('deltaTtestpoles',deltaTtestpoles, 0.0)     !--- For modif_sst>=2
     210         CALL get_in( 'sstlatcrit',    sstlatcrit,     30.0)     !--- For modif_sst>=3
     211         CALL get_in('dsstlatcrit',   dsstlatcrit,      0.0)     !--- For modif_sst>=3
    217212#ifdef ISOVERIF
    218    CALL msg('iso_init 270:  sstlatcrit='//real2str( sstlatcrit), modname, sstlatcrit < 0.0) !--- For modif_sst>=2
    219    CALL msg('iso_init 279: dsstlatcrit='//real2str(dsstlatcrit), modname, sstlatcrit < 0.0) !--- For modif_sst>=3
    220    IF(modif_sst >= 2 .AND. sstlatcrit < 0.0) STOP
     213         CALL msg('iso_init 270:  sstlatcrit='//real2str( sstlatcrit), modname, sstlatcrit < 0.0) !--- For modif_sst>=2
     214         CALL msg('iso_init 279: dsstlatcrit='//real2str(dsstlatcrit), modname, sstlatcrit < 0.0) !--- For modif_sst>=3
     215         IF(modif_sst >= 2 .AND. sstlatcrit < 0.0) STOP
    221216#endif             
    222217
    223    CALL get_in('modif_sic', modif_sic,  0)
    224    IF(modif_sic >= 1) &
    225    CALL get_in('deltasic',  deltasic, 0.1)
    226 
    227    CALL get_in('albedo_prescrit', albedo_prescrit, 0)
    228    IF(albedo_prescrit == 1) THEN
    229       CALL get_in('lon_min_albedo', lon_min_albedo, -200.)
    230       CALL get_in('lon_max_albedo', lon_max_albedo,  200.)
    231       CALL get_in('lat_min_albedo', lat_min_albedo, -100.)
    232       CALL get_in('lat_max_albedo', lat_max_albedo,  100.)
    233    END IF
    234    CALL get_in('deltaP_BL',           deltaP_BL,     10.0)
    235    CALL get_in('ruissellement_pluie', ruissellement_pluie, 0)
    236    CALL get_in('alphak_stewart',      alphak_stewart,      1)
    237    CALL get_in('tdifexp_sol',         tdifexp_sol,      0.67)
    238    CALL get_in('calendrier_guide',    calendrier_guide,    0)
    239    CALL get_in('cste_surf_cond',      cste_surf_cond,      0)
    240    CALL get_in('mixlen',              mixlen,           35.0)
    241    CALL get_in('evap_cont_cste',      evap_cont_cste,      0)
    242    CALL get_in('deltaO18_evap_cont',  deltaO18_evap_cont,0.0)
    243    CALL get_in('d_evap_cont',         d_evap_cont,       0.0)
    244    CALL get_in('nudge_qsol',          nudge_qsol,          0)
    245    CALL get_in('region_nudge_qsol',   region_nudge_qsol,   1)
    246    nlevmaxO17 = 50
    247    CALL msg('nlevmaxO17='//TRIM(int2str(nlevmaxO17)))
    248    CALL get_in('no_pce',   no_pce,     0)
    249    CALL get_in('A_satlim', A_satlim, 1.0)
    250    CALL get_in('ok_restrict_A_satlim', ok_restrict_A_satlim, 0)
     218         CALL get_in('modif_sic', modif_sic,  0)
     219         IF(modif_sic >= 1) &
     220         CALL get_in('deltasic',  deltasic, 0.1)
     221
     222         CALL get_in('albedo_prescrit', albedo_prescrit, 0)
     223         IF(albedo_prescrit == 1) THEN
     224            CALL get_in('lon_min_albedo', lon_min_albedo, -200.)
     225            CALL get_in('lon_max_albedo', lon_max_albedo,  200.)
     226            CALL get_in('lat_min_albedo', lat_min_albedo, -100.)
     227            CALL get_in('lat_max_albedo', lat_max_albedo,  100.)
     228         END IF
     229         CALL get_in('deltaO18_oce',        deltaO18_oce,   0.0)
     230         CALL get_in('deltaP_BL',           deltaP_BL,     10.0)
     231         CALL get_in('ruissellement_pluie', ruissellement_pluie, 0)
     232         CALL get_in('alphak_stewart',      alphak_stewart,      1)
     233         CALL get_in('tdifexp_sol',         tdifexp_sol,      0.67)
     234         CALL get_in('calendrier_guide',    calendrier_guide,    0)
     235         CALL get_in('cste_surf_cond',      cste_surf_cond,      0)
     236         CALL get_in('mixlen',              mixlen,           35.0)
     237         CALL get_in('evap_cont_cste',      evap_cont_cste,      0)
     238         CALL get_in('deltaO18_evap_cont',  deltaO18_evap_cont,0.0)
     239         CALL get_in('d_evap_cont',         d_evap_cont,       0.0)
     240         CALL get_in('nudge_qsol',          nudge_qsol,          0)
     241         CALL get_in('region_nudge_qsol',   region_nudge_qsol,   1)
     242         nlevmaxO17 = 50
     243         CALL msg('nlevmaxO17='//TRIM(int2str(nlevmaxO17)))
     244         CALL get_in('no_pce',   no_pce,     0)
     245         CALL get_in('A_satlim', A_satlim, 1.0)
     246         CALL get_in('ok_restrict_A_satlim', ok_restrict_A_satlim, 0)
    251247#ifdef ISOVERIF
    252    CALL msg(' 315: A_satlim='//real2str(A_satlim), modname, A_satlim > 1.0)
    253    IF(A_satlim > 1.0) STOP
     248         CALL msg(' 315: A_satlim='//real2str(A_satlim), modname, A_satlim > 1.0)
     249         IF(A_satlim > 1.0) STOP
    254250#endif
    255 !  CALL get_in('slope_limiterxy',   slope_limiterxy,  2.0)
    256 !  CALL get_in('slope_limiterz',    slope_limiterz,   2.0)
    257    CALL get_in('modif_ratqs',       modif_ratqs,        0)
    258    CALL get_in('Pcrit_ratqs',       Pcrit_ratqs,    500.0)
    259    CALL get_in('ratqsbasnew',       ratqsbasnew,     0.05)
    260    CALL get_in('fac_modif_evaoce',  fac_modif_evaoce, 1.0)
    261    CALL get_in('ok_bidouille_wake', ok_bidouille_wake,  0)
    262    ! si oui, la temperature de cond est celle de l'environnement, pour eviter
    263    ! bugs quand temperature dans ascendances convs est mal calculee
    264    CALL get_in('cond_temp_env',        cond_temp_env,        .FALSE.)
    265    IF(ANY(isoName == 'HTO')) &
    266    CALL get_in('ok_prod_nucl_tritium', ok_prod_nucl_tritium, .FALSE., .FALSE.)
    267 
    268    ! Ocean composition
    269    CALL get_in('deltaO18_oce',  deltaO18_oce, 0.0)
    270    
    271    CALL msg('iso_O18, iso_HDO, iso_eau = '//TRIM(strStack(int2str([iso_O18, iso_HDO, iso_eau]))), modname)
    272 
    273    !--------------------------------------------------------------
    274    ! Isotope fractionation factors and a few isotopic constants
    275    !--------------------------------------------------------------
    276    ALLOCATE(tkcin0(niso))
    277    ALLOCATE(tkcin1(niso))
    278    ALLOCATE(tkcin2(niso))
    279    ALLOCATE(tnat(niso))
    280    ALLOCATE(tdifrel(niso))
    281    ALLOCATE(toce(niso))
    282    ALLOCATE(tcorr(niso))
    283    ALLOCATE(talph1(niso))
    284    ALLOCATE(talph2(niso))
    285    ALLOCATE(talph3(niso))
    286    ALLOCATE(talps1(niso))
    287    ALLOCATE(talps2(niso))
    288    ALLOCATE(alpha_liq_sol(niso))
    289    ALLOCATE(Rdefault(niso))
    290    ALLOCATE(Rmethox(niso))
    291 
    292    do ixt=1,niso
    293      if (ixt.eq.iso_HTO) then  ! Tritium
    294        tkcin0(ixt) = 0.01056
    295        tkcin1(ixt) = 0.0005016
    296        tkcin2(ixt) = 0.0014432
    297        if (tnat1) then
    298                tnat(ixt)=1
    299        else
    300                tnat(ixt)=0.
    301        endif
    302        toce(ixt)=4.0E-19 ! rapport T/H = 0.2 TU Dreisigacker and Roether 1978
    303        tcorr(ixt)=1.
    304        tdifrel(ixt)=1./0.968
    305        talph1(ixt)=46480.
    306        talph2(ixt)=-103.87
    307        talph3(ixt)=0.
    308        talps1(ixt)=46480.
    309        talps2(ixt)=-103.87
    310        alpha_liq_sol(ixt)=1.
    311        Rmethox(ixt)=0.0
    312      endif
    313      if (ixt.eq.iso_O17) then  ! O17
    314        pente_MWL=0.528
    315        tdifrel(ixt)=1./0.98555 ! valeur utilisée en 1D et dans modèle de LdG ! tdifrel(ixt)=1./0.985452 ! donné par Amaelle
    316        fac_kcin= (tdifrel(ixt)-1.0)/(tdifrel_O18-1.0) ! fac_kcin=0.5145 ! donné par Amaelle
    317        tkcin0(ixt) = tkcin0_O18*fac_kcin
    318        tkcin1(ixt) = tkcin1_O18*fac_kcin
    319        tkcin2(ixt) = tkcin2_O18*fac_kcin
    320        if (tnat1) then
    321                tnat(ixt)=1
    322        else
    323                tnat(ixt)=0.004/100. ! O17 représente 0.004% de l'oxygène
    324        endif
    325        toce(ixt)=tnat(ixt)*(1.0+deltaO18_oce/1000.0)**pente_MWL
    326        tcorr(ixt)=1.0+fac_enrichoce18*pente_MWL ! donné par Amaelle           
    327        talph1(ixt)=talph1_O18
    328        talph2(ixt)=talph2_O18
    329        talph3(ixt)=talph3_O18
    330        talps1(ixt)=talps1_O18
    331        talps2(ixt)=talps2_O18     
    332        alpha_liq_sol(ixt)=(alpha_liq_sol_O18)**fac_coeff_eq17_liq
    333        Rdefault(ixt)=tnat(ixt)*(-3.15/1000.0+1.0)
    334        Rmethox(ixt)=(230./1000.+1.)*tnat(ixt) !Zahn et al 2006
    335      endif
    336      if (ixt.eq.iso_O18) then  ! Oxygene18
    337        tkcin0(ixt) = tkcin0_O18
    338        tkcin1(ixt) = tkcin1_O18
    339        tkcin2(ixt) = tkcin2_O18
    340        if (tnat1) then
    341                tnat(ixt)=1
    342        else
    343                tnat(ixt)=2005.2E-6
    344        endif
    345        toce(ixt)=tnat(ixt)*(1.0+deltaO18_oce/1000.0)
    346        tcorr(ixt)=1.0+fac_enrichoce18
    347        tdifrel(ixt)=tdifrel_O18
    348        talph1(ixt)=talph1_O18
    349        talph2(ixt)=talph2_O18
    350        talph3(ixt)=talph3_O18
    351        talps1(ixt)=talps1_O18
    352        talps2(ixt)=talps2_O18
    353        alpha_liq_sol(ixt)=alpha_liq_sol_O18   
    354        Rdefault(ixt)=tnat(ixt)*(-6.0/1000.0+1.0)
    355        Rmethox(ixt)=(130./1000.+1.)*tnat(ixt) !Zahn et al 2006 
    356      endif
    357      if (ixt.eq.iso_HDO) then ! Deuterium
    358        pente_MWL=8.0
    359        tdifrel(ixt)=1./0.9755 !          fac_kcin=0.88
    360        fac_kcin= (tdifrel(ixt)-1)/(tdifrel_O18-1)
    361        tkcin0(ixt) = tkcin0_O18*fac_kcin
    362        tkcin1(ixt) = tkcin1_O18*fac_kcin
    363        tkcin2(ixt) = tkcin2_O18*fac_kcin
    364        if (tnat1) then
    365                tnat(ixt)=1
    366        else
    367                tnat(ixt)=155.76E-6
    368        endif
    369        toce(ixt)=tnat(ixt)*(1.0+pente_MWL*deltaO18_oce/1000.0)
    370        tcorr(ixt)=1.0+fac_enrichoce18*pente_MWL         
    371        talph1(ixt)=24844.
    372        talph2(ixt)=-76.248
    373        talph3(ixt)=52.612E-3
    374        talps1(ixt)=16288.
    375        talps2(ixt)=-0.0934
    376        !ZXalpha_liq_sol=1.0192 ! Weston, Ralph, 1955
    377        alpha_liq_sol(ixt)=1.0212
    378        ! valeur de Lehmann & Siegenthaler, 1991, Journal of
    379        ! Glaciology, vol 37, p 23
    380        Rdefault(ixt)=tnat(ixt)*((-6.0*pente_MWL+10.0)/1000.0+1.0)
    381        Rmethox(ixt)=tnat(ixt)*(-25.0/1000.+1.) ! Zahn et al 2006
    382      endif
    383      if (ixt.eq.iso_eau) then ! Oxygene16
    384        tkcin0(ixt) = 0.0
    385        tkcin1(ixt) = 0.0
    386        tkcin2(ixt) = 0.0
    387        tnat(ixt)=1.
    388        toce(ixt)=tnat(ixt)
    389        tcorr(ixt)=1.0
    390        tdifrel(ixt)=1.
    391        talph1(ixt)=0.
    392        talph2(ixt)=0.
    393        talph3(ixt)=0.
    394        talps1(ixt)=0.
    395        talph3(ixt)=0.
    396        alpha_liq_sol(ixt)=1.
    397        Rdefault(ixt)=tnat(ixt)*1.0
    398        Rmethox(ixt)=1.0
    399      endif
    400    enddo ! ixt=1,niso
    401 
    402    IF(.NOT.Rdefault_smow) then
    403         Rdefault(:) = 0.0
    404         if (iso_eau.gt.0) Rdefault(iso_eau) = 1.0 ! correction Camille 30 mars 2023
    405    ENDIF
    406    write(*,*) 'Rdefault=',Rdefault
    407    write(*,*) 'toce=',toce
    408 
    409    !--- Sensitivity test: no kinetic effect in sfc evaporation
    410    IF(ok_nocinsfc) THEN
    411       tkcin0(1:niso) = 0.0
    412       tkcin1(1:niso) = 0.0
    413       tkcin2(1:niso) = 0.0
    414    END IF
    415 
    416    CALL msg('285: verif initialisation:', modname)
    417    DO ixt=1,niso
    418       sxt=int2str(ixt)
    419       CALL msg(' * isoName('//TRIM(sxt)//') = <'//TRIM(isoName(ixt))//'>',  modname)
    420       CALL msg(  '    tnat('//TRIM(sxt)//') = '//TRIM(real2str(tnat(ixt))), modname)
    421 !     CALL msg('    alpha_liq_sol('//TRIM(sxt)//') = '//TRIM(real2str(alpha_liq_sol(ixt))), modname)
    422 !     CALL msg(        '   tkcin0('//TRIM(sxt)//') = '//TRIM(real2str(tkcin0(ixt))),        modname)
    423 !     CALL msg(       '   tdifrel('//TRIM(sxt)//') = '//TRIM(real2str(tdifrel(ixt))),       modname)
     251!        CALL get_in('slope_limiterxy',   slope_limiterxy,  2.0)
     252!        CALL get_in('slope_limiterz',    slope_limiterz,   2.0)
     253         CALL get_in('modif_ratqs',       modif_ratqs,        0)
     254         CALL get_in('Pcrit_ratqs',       Pcrit_ratqs,    500.0)
     255         CALL get_in('ratqsbasnew',       ratqsbasnew,     0.05)
     256         CALL get_in('fac_modif_evaoce',  fac_modif_evaoce, 1.0)
     257         CALL get_in('ok_bidouille_wake', ok_bidouille_wake,  0)
     258         ! si oui, la temperature de cond est celle de l'environnement, pour eviter
     259         ! bugs quand temperature dans ascendances convs est mal calculee
     260         CALL get_in('cond_temp_env',        cond_temp_env,        .FALSE.)
     261         IF(ANY(isoName == 'HTO')) &
     262         CALL get_in('ok_prod_nucl_tritium', ok_prod_nucl_tritium, .FALSE., .FALSE.)
     263         CALL get_in('tnateq1', ltnat1, .TRUE.)
     264
     265         CALL msg('iso_O18, iso_HDO, iso_eau = '//TRIM(strStack(int2str([iso_O18, iso_HDO, iso_eau]))), modname)
     266
     267         !--------------------------------------------------------------
     268         ! Parameters that depend on the nature of water isotopes:
     269         !--------------------------------------------------------------
     270         ALLOCATE(tnat (niso), talph1(niso),  talps1(niso), tkcin0(niso), tdifrel (niso), alpha        (niso))
     271         ALLOCATE(toce (niso), talph2(niso),  talps2(niso), tkcin1(niso), Rdefault(niso), alpha_liq_sol(niso))
     272         ALLOCATE(tcorr(niso), talph3(niso),                tkcin2(niso), Rmethox (niso))
     273
     274         !=== H216O
     275         is = iso_eau
     276         IF(is /= 0) THEN
     277            tdifrel (is) = 1.0
     278            alpha   (is) = alpha_ideal_H216O
     279            tnat    (is) = tnat_H216O; IF(ltnat1) tnat(is) = 1.0
     280            toce    (is) = tnat(is)
     281            tcorr   (is) = 1.0
     282            talph1  (is) = 0.0;  talps1(is) = 0.0;  tkcin0(is)  = 0.0
     283            talph2  (is) = 0.0;  talps2(is) = 0.0;  tkcin1(is)  = 0.0
     284            talph3  (is) = 0.0;                     tkcin2(is)  = 0.0
     285            Rdefault(is) = tnat(is)*1.0
     286            Rmethox (is) = 1.0
     287            alpha_liq_sol(is) = 1.0
     288         END IF
     289
     290         !=== H217O
     291         is = iso_O17
     292         IF(is /= 0) THEN; pente_MWL = 0.528
     293            tdifrel (is) = 1./0.98555  ! used in 1D and in LdG model ; tdifrel=1./0.985452: from Amaelle
     294            alpha   (is) = alpha_ideal_H217O
     295            tnat    (is) = tnat_H217O; IF(ltnat1) tnat(is) = 1.0
     296            toce    (is) = tnat(is)*(1.0+deltaO18_oce/1000.0)**pente_MWL
     297            tcorr   (is) = 1.0+fac_enrichoce18*pente_MWL
     298            fac_kcin = (tdifrel(is)-1.0)/(tdifrel_O18-1.0)           ! fac_kcin=0.5145:     from Amaelle
     299            talph1  (is) = talph1_O18;  talps1(is) = talps1_O18;  tkcin0(is) = tkcin0_O18*fac_kcin
     300            talph2  (is) = talph2_O18;  talps2(is) = talps2_O18;  tkcin1(is) = tkcin1_O18*fac_kcin
     301            talph3  (is) = talph3_O18;                            tkcin2(is) = tkcin2_O18*fac_kcin
     302            Rdefault(is) = tnat(is)*(1.0-3.15/1000.)
     303            Rmethox (is) = tnat(is)*(1.0+230./1000.)
     304            alpha_liq_sol(is) = alpha_liq_sol_O18**fac_coeff_eq17_liq
     305         END IF
     306
     307         !=== H218O
     308         is = iso_O18
     309         IF(is /= 0) THEN
     310            tdifrel (is) = tdifrel_O18
     311            alpha   (is) = alpha_ideal_H218O
     312            tnat    (is) = tnat_H218O; IF(ltnat1) tnat(is) = 1.0
     313            toce    (is) = tnat(is)*(1.0+deltaO18_oce/1000.0)
     314            tcorr   (is) = 1.0+fac_enrichoce18
     315            talph1  (is) = talph1_O18;  talps1(is) = talps1_O18;  tkcin0(is) = tkcin0_O18
     316            talph2  (is) = talph2_O18;  talps2(is) = talps2_O18;  tkcin1(is) = tkcin1_O18
     317            talph3  (is) = talph3_O18;                            tkcin2(is) = tkcin2_O18
     318            Rdefault(is) = tnat(is)*(1.0-6.00/1000.)
     319            Rmethox (is) = tnat(is)*(1.0+130./1000.)  ! Zahn & al. 2006
     320            alpha_liq_sol(is) = alpha_liq_sol_O18
     321         END IF
     322
     323         !=== HDO
     324         is = iso_HDO
     325         IF(is /= 0) THEN; pente_MWL = 8.0
     326            tdifrel (is) = 1./0.9755                  ! fac_kcin=0.88
     327            alpha   (is) = alpha_ideal_HDO
     328            tnat    (is) = tnat_HDO; IF(ltnat1) tnat(is) = 1.0
     329            toce    (is) = tnat(is)*(1.0+deltaO18_oce/1000.0*pente_MWL)
     330            tcorr   (is) = 1.0+fac_enrichoce18*pente_MWL
     331            fac_kcin = (tdifrel(is)-1.0)/(tdifrel_O18-1.0)
     332            talph1  (is) = 24844.;      talps1(is) = 16288.;      tkcin0(is) = tkcin0_O18*fac_kcin
     333            talph2  (is) = -76.248;     talps2(is) = -0.0934;     tkcin1(is) = tkcin1_O18*fac_kcin
     334            talph3  (is) = 52.612E-3;                             tkcin2(is) = tkcin2_O18*fac_kcin
     335            Rdefault(is) = tnat(is)*(1.0+(10.0-6.0*pente_MWL)/1000.)
     336            Rmethox (is) = tnat(is)*(1.0-25.0/1000.)
     337            alpha_liq_sol(is) = 1.0212      ! Lehmann & Siegenthaler, 1991, Jo. of Glaciology, vol 37, p 23
     338                                            ! alpha_liq_sol=1.0192: Weston, Ralph, 1955
     339         END IF
     340
     341         !=== HTO
     342         is = iso_HTO
     343         IF(is /= 0) THEN
     344            tdifrel (is) = 1./0.968
     345            alpha   (is) = alpha_ideal_HTO
     346            tnat    (is) = tnat_HTO; IF(ltnat1) tnat(is) = 1.0
     347            toce    (is) = 4.0E-19          ! ratio T/H = 0.2 TU Dreisigacker & Roether 1978
     348            tcorr   (is) = 1.0
     349            talph1  (is) = 46480.;      talps1(is) = 46480.;      tkcin0(is) = 0.01056
     350            talph2  (is) = -103.87;     talps2(is) = -103.87;     tkcin1(is) = 0.0005016
     351            talph3  (is) = 0.0;                                   tkcin2(is) = 0.0014432
     352            Rdefault(is) = 0.0
     353            Rmethox (is) = 0.0
     354            alpha_liq_sol(is) = 1.0
     355         END IF
     356
     357         IF(.NOT. Rdefault_smow) THEN
     358            Rdefault(:) = 0.0; IF(iso_eau > 0) Rdefault(iso_eau) = 1.0
     359         END IF
     360         WRITE(*,*) 'Rdefault = ',Rdefault
     361         WRITE(*,*) 'toce = ', toce
     362
     363         !--- Sensitivity test: no kinetic effect in sfc evaporation
     364         IF(ok_nocinsfc) THEN
     365            tkcin0(1:niso) = 0.0
     366            tkcin1(1:niso) = 0.0
     367            tkcin2(1:niso) = 0.0
     368         END IF
     369
     370         CALL msg('285: verif initialisation:', modname)
     371         DO ixt=1,niso
     372            sxt=int2str(ixt)
     373            CALL msg(' * isoName('//TRIM(sxt)//') = <'//TRIM(isoName(ixt))//'>',  modname)
     374            CALL msg(  '    tnat('//TRIM(sxt)//') = '//TRIM(real2str(tnat(ixt))), modname)
     375!           CALL msg('    alpha_liq_sol('//TRIM(sxt)//') = '//TRIM(real2str(alpha_liq_sol(ixt))), modname)
     376!           CALL msg(        '   tkcin0('//TRIM(sxt)//') = '//TRIM(real2str(tkcin0(ixt))),        modname)
     377!           CALL msg(       '   tdifrel('//TRIM(sxt)//') = '//TRIM(real2str(tdifrel(ixt))),       modname)
     378         END DO
     379         CALL msg('69:     lambda = '//TRIM(real2str(lambda_sursat)), modname)
     380         CALL msg('69:    thumxt1 = '//TRIM(real2str(thumxt1)),       modname)
     381         CALL msg('69: h_land_ice = '//TRIM(real2str(h_land_ice)),    modname)
     382         CALL msg('69:      P_veg = '//TRIM(real2str(P_veg)),         modname)
     383!==============================================================================================================================
     384      ELSE
     385!==============================================================================================================================
     386         CALL abort_physic('"isotopes_mod" is not set up yet for isotopes family "'//TRIM(isoFamilies(ii))//'"', modname, 1)
     387!==============================================================================================================================
     388      END IF
     389!==============================================================================================================================
    424390   END DO
    425    CALL msg('69:     lambda = '//TRIM(real2str(lambda_sursat)), modname)
    426    CALL msg('69:    thumxt1 = '//TRIM(real2str(thumxt1)),       modname)
    427    CALL msg('69: h_land_ice = '//TRIM(real2str(h_land_ice)),    modname)
    428    CALL msg('69:      P_veg = '//TRIM(real2str(P_veg)),         modname)
    429391
    430392END SUBROUTINE iso_init
  • LMDZ6/trunk/libf/phylmdiso/isotopes_routines_mod.F90

    r5084 r5183  
    1641916419   USE isotopes_mod,      ONLY: isoName,iso_HDO,iso_eau
    1642016420   USE phyetat0_get_mod,  ONLY: phyetat0_get, phyetat0_srf
    16421    USE readTracFiles_mod, ONLY: new2oldH2O
    16422    USE strings_mod,       ONLY: strIdx, strTail, maxlen, msg, int2str
     16421   USE infotrac_phy,      ONLY: new2oldH2O
     16422   USE strings_mod,       ONLY: strIdx, strHead, strTail, maxlen, msg, int2str
    1642316423#ifdef ISOVERIF
    1642416424   USE isotopes_verif_mod
     
    1645916459      outiso = isoName(ixt)
    1646016460      oldIso = strTail(new2oldH2O(outiso), '_')            !--- Remove "H2O_" from "H2O_<iso>[_<tag>]"
    16461       i = INDEX(outiso, '_', .TRUE.)
    16462       oldIso2 = outiso(1:i-1)//outiso(i+1:LEN_TRIM(outiso)) ! CR 2023: on ajoute cette possibilité aussi, elle correspond au cas le plus récent.
     16461      oldIso2= TRIM(strHead(outiso,'_'))//strTail(outiso,'_') ! CR 2023: most recent possibility
    1646316462!      write(*,*) 'tmp 16541:'
    1646416463!      write(*,*) 'outiso=',outiso
  • LMDZ6/trunk/libf/phylmdiso/isotrac_mod.F90

    r4493 r5183  
    33
    44MODULE isotrac_mod
    5   USE infotrac_phy,      ONLY: niso, ntiso, nzone
    6   USE readTracFiles_mod, ONLY: delPhase
    7   USE isotopes_mod,      ONLY: ridicule, get_in
     5  USE infotrac_phy, ONLY: niso, ntiso, nzone, delPhase
     6  USE isotopes_mod, ONLY: ridicule, get_in
    87
    98  IMPLICIT NONE
  • LMDZ6/trunk/libf/phylmdiso/phyetat0_mod.F90

    r5084 r5183  
    4040  USE geometry_mod,     ONLY: longitude_deg, latitude_deg
    4141  USE iostart,          ONLY: close_startphy, get_field, get_var, open_startphy
    42   USE infotrac_phy,     ONLY: nqtot, nbtr, type_trac, tracers
    43   USE readTracFiles_mod,ONLY: maxlen, new2oldH2O
     42  USE infotrac_phy,     ONLY: nqtot, nbtr, type_trac, tracers, new2oldH2O
     43  USE strings_mod,      ONLY: maxlen
    4444  USE traclmdz_mod,     ONLY: traclmdz_from_restart
    4545  USE carbon_cycle_mod, ONLY: carbon_cycle_init, carbon_cycle_cpl, carbon_cycle_tr, carbon_cycle_rad, co2_send, RCO2_glo
  • LMDZ6/trunk/libf/phylmdiso/physiq_mod.F90

    r5169 r5183  
    3939    USE ioipsl_getin_p_mod, ONLY : getin_p
    4040    USE indice_sol_mod
    41     USE infotrac_phy, ONLY: nqtot, nbtr, nqo, tracers, type_trac,ivap,iliq,isol
    42     USE readTracFiles_mod, ONLY: addPhase
     41    USE infotrac_phy, ONLY: nqtot, nbtr, nqo, tracers, type_trac,addPhase, ivap, iliq, isol
    4342    USE strings_mod,  ONLY: strIdx
    4443    USE iophy
Note: See TracChangeset for help on using the changeset viewer.