Changeset 2


Ignore:
Timestamp:
Dec 8, 2021, 9:25:11 PM (3 years ago)
Author:
dcugnet
Message:
  • string_mod.F90:
    • Fix: use ioipsl_getincom (and the non-existing not ioipsl_getin_mod).
    • Nominal strings length is now a parameter (maxlen).
    • No global "modname" used -> modified "msg" routines with corresponding "modname" optional argument.
  • trac_types_mod.F90:
    • Longer and more explicit names for most of the entries.
    • itr component removed, but two new components (isAdvected and isH2Ofamily) help to keep iq=1,nqtot loops only and drop elements to be avoided in most physical routines just by using a conditional CYCLE.
  • readTracFiles_mod.F90:
    • Derived type 'dataBase_type' (formerly "db"), only used in this routine, is moved from "trac_types_mod" to here.
    • String length is now a parameter (maxlen), taken from "strings_mod.F90".
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • readTracFiles_mod.f90

    r1 r2  
    11MODULE readTracFiles_mod
    22
    3   USE strings_mod, ONLY: msg, testFile,  strFind, strStack, strReduce,  strHead, strCount,   find, dispTable, fmsg, &
    4           removeComment, cat, checkList, strIdx,  strParse, strReplace, strTail, reduceExpr, test, modname, get_in
    5   USE trac_types_mod, ONLY : tra, iso, db, kys
     3  USE strings_mod, ONLY:   msg, testFile,  strFind, strStack, strReduce,  strHead, strCount,   find, maxlen, fmsg, &
     4            removeComment, cat, checkList, strIdx,  strParse, strReplace, strTail, reduceExpr, test, get_in, dispTable
     5  USE trac_types_mod, ONLY : trac_type, isot_type, keys_type
    66
    77  IMPLICIT NONE
     
    1010
    1111  PUBLIC :: initIsotopes
    12   PUBLIC :: readTracersFiles, aliasTracer, tracersSubset, indexUpdate     !--- TOOLS ASSOCIATED TO TRACERS  DESCRIPTORS
    13   PUBLIC :: readIsotopesFile                                              !--- TOOLS ASSOCIATED TO ISOTOPES DESCRIPTORS
    14   PUBLIC :: getKey_init, getKey, setDirectKeys                            !--- FUNCTIONS TO GET KEYS FROM tracers & isotopes
    15 
    16   PUBLIC :: known_phases, old_phases, nphases, phases_names, phases_sep, &!--- VARIABLES RELATED TO THE PHASES
    17             delPhase, addPhase                                            !--- ROUTINES TO ADD/REMOVE PHASE TO/FROM A NAME
    18 
    19   PUBLIC :: tran0, idxAncestor, ancestor                                  !--- GEN 0 TRACER + TOOLS FOR GENERATIONS
    20 
    21 !------------------------------------------------------------------------------------------------------------------------------
    22   TYPE db                                                            !=== TYPE FOR TRACERS SECTION
    23     CHARACTER(LEN=256)     :: name                                   !--- Section name
    24     TYPE(tra), ALLOCATABLE :: trac(:)                                !--- Tracers descriptors
    25   END TYPE db
     12  PUBLIC :: readTracersFiles, aliasTracer, tracersSubset, indexUpdate!--- TOOLS ASSOCIATED TO TRACERS  DESCRIPTORS
     13  PUBLIC :: readIsotopesFile                                         !--- TOOLS ASSOCIATED TO ISOTOPES DESCRIPTORS
     14  PUBLIC :: getKey_init, getKey, setDirectKeys                       !--- GET/SET KEYS FROM/TO tracers & isotopes
     15
     16  PUBLIC :: known_phases, old_phases, nphases, phases_names, &       !--- VARIABLES RELATED TO THE PHASES
     17            phases_sep, delPhase, addPhase                           !--- + ROUTINES TO ADD/REMOVE PHASE TO/FROM A NAME
     18
     19  PUBLIC :: tran0, idxAncestor, ancestor                             !--- GENERATION 0 TRACER + TOOLS FOR GENERATIONS
     20
     21!------------------------------------------------------------------------------------------------------------------------------
     22  TYPE :: dataBase_type                                              !=== TYPE FOR TRACERS SECTION
     23    CHARACTER(LEN=maxlen)  :: name                                   !--- Section name
     24    TYPE(trac_type), ALLOCATABLE :: trac(:)                          !--- Tracers descriptors
     25  END TYPE dataBase_type
    2626!------------------------------------------------------------------------------------------------------------------------------
    2727  INTERFACE getKey
     
    2929  END INTERFACE getKey
    3030!------------------------------------------------------------------------------------------------------------------------------
    31   INTERFACE tracersSubset; MODULE PROCEDURE trSubset_Indx, trSubset_Name, trSubset_Nam1; END INTERFACE tracersSubset
     31  INTERFACE tracersSubset; MODULE PROCEDURE trSubset_Indx, trSubset_Name, trSubset_gen0Name; END INTERFACE tracersSubset
    3232  INTERFACE idxAncestor;   MODULE PROCEDURE idxAncestor_1, idxAncestor_m; END INTERFACE idxAncestor
    3333  INTERFACE    ancestor;   MODULE PROCEDURE    ancestor_1,    ancestor_m; END INTERFACE    ancestor
     
    3636
    3737  !=== MAIN DATABASE: files sections descriptors
    38   TYPE(db), SAVE, ALLOCATABLE, TARGET :: dBase(:)
     38  TYPE(dataBase_type), SAVE, ALLOCATABLE, TARGET :: dBase(:)
    3939
    4040  !--- SOME PARAMETERS THAT ARE NOT LIKELY TO CHANGE OFTEN
    41   CHARACTER(LEN=256), SAVE      :: tran0        = 'air'              !--- Default transporting fluid
    42   CHARACTER(LEN=256), PARAMETER :: old_phases   = 'vli'              !--- Old phases for water (no separator)
    43   CHARACTER(LEN=256), PARAMETER :: known_phases = 'gls'              !--- Known phases initials
    44   INTEGER,            PARAMETER :: nphases = LEN_TRIM(known_phases) !--- Number of phases
    45   CHARACTER(LEN=256), SAVE      :: phases_names(nphases) &           !--- Known phases names
    46                                  = ['gaseous', 'liquid ', 'solid  ']
     41  CHARACTER(LEN=maxlen), SAVE      :: tran0        = 'air'           !--- Default transporting fluid
     42  CHARACTER(LEN=maxlen), PARAMETER :: old_phases   = 'vli'           !--- Old phases for water (no separator)
     43  CHARACTER(LEN=maxlen), PARAMETER :: known_phases = 'gls'           !--- Known phases initials
     44  INTEGER,               PARAMETER :: nphases=LEN_TRIM(known_phases) !--- Number of phases
     45  CHARACTER(LEN=maxlen), SAVE      :: phases_names(nphases) &        !--- Known phases names
     46                                = ['gaseous', 'liquid ', 'solid  ']
    4747  CHARACTER(LEN=1),   SAVE      :: phases_sep  =  '_'                !--- Phase separator
    4848  LOGICAL,            SAVE      :: tracs_merge = .TRUE.              !--- Merge/stack tracers lists
     
    5050
    5151  !=== LOCAL COPIES OF THE TRACERS AND ISOTOPES DESCRIPTORS, USED BY getKey (INITIALIZED IN getKey_init)
    52   TYPE(tra), ALLOCATABLE, TARGET, SAVE ::  tracers(:)
    53   TYPE(iso), ALLOCATABLE, TARGET, SAVE :: isotopes(:)
    54 
     52  TYPE(trac_type), ALLOCATABLE, TARGET, SAVE ::  tracers(:)
     53  TYPE(isot_type), ALLOCATABLE, TARGET, SAVE :: isotopes(:)
     54
     55  CHARACTER(LEN=maxlen) :: modname
    5556
    5657CONTAINS
     
    7374!=== FUNCTION RETURN VALUE "lerr" IS FALSE IN CASE SOMETHING WENT WRONG.
    7475!=== ABOUT THE KEYS:
    75 !     * The "keys" component (of type kys) is in principle enough to store everything we could need.
     76!     * The "keys" component (of type keys_type) is in principle enough to store everything we could need.
    7677!     But some variables are stored as direct-access keys to make the code more readable and because they are used often.
    7778!     * Most of the direct-access keys are set in this module, but some are not (lnam, iadv and itr for example).
    7879!     * Some of the direct-access keys must be updated (using the routine "setDirectKeys") is a subset of "tracers(:)"
    79 !     is extracted: the indexes are no longer valid for a subset (examples: tracers(:)iprnt or tracers(:)%ichld).
     80!     is extracted: the indexes are no longer valid for a subset (examples: tracers(:)%iqParent or tracers(:)%ichld).
    8081!     * If you need to convert a %key/%val pair into a direct-access key, add the corresponding line in "setDirectKeys".
    8182!==============================================================================================================================
    8283LOGICAL FUNCTION readTracersFiles(type_trac, fType, tracs) RESULT(lerr)
    8384!------------------------------------------------------------------------------------------------------------------------------
    84   CHARACTER(LEN=*),       INTENT(IN)  :: type_trac                    !--- List of components used
    85   INTEGER,                INTENT(OUT) :: fType                        !--- Type of input file found
    86   TYPE(tra), ALLOCATABLE, INTENT(OUT) :: tracs(:)
    87   CHARACTER(LEN=256),     ALLOCATABLE ::  s(:), sections(:), trac_files(:)
    88   CHARACTER(LEN=256)  :: str, fname, mesg
    89   INTEGER              :: is, nsec, ierr, it, ntrac, ns, ip
    90   LOGICAL, ALLOCATABLE :: ll(:), lGen3(:)
     85  CHARACTER(LEN=*),             INTENT(IN)  :: type_trac              !--- List of components used
     86  INTEGER,                      INTENT(OUT) :: fType                  !--- Type of input file found
     87  TYPE(trac_type), ALLOCATABLE, INTENT(OUT) :: tracs(:)
     88  CHARACTER(LEN=maxlen),  ALLOCATABLE ::  s(:), sections(:), trac_files(:)
     89  CHARACTER(LEN=maxlen) :: str, fname, mesg
     90  INTEGER               :: is, nsec, ierr, it, ntrac, ns, ip
     91  LOGICAL, ALLOCATABLE  :: ll(:), lGen3(:)
    9192!------------------------------------------------------------------------------------------------------------------------------
    9293  lerr = .FALSE.
    93 !  modname = 'readTracersFiles'
     94  modname = 'readTracersFiles'
    9495  IF(.NOT.ALLOCATED(dBase)) ALLOCATE(dBase(0))
    9596
     
    111112
    112113  !--- TELLS WHAT WAS IS ABOUT TO BE USED
    113   IF( fmsg(fType==0, 'No adequate tracers description file(s) found ; default values will be used')) RETURN
    114   CALL msg(fType==1, 'Trying to read old-style tracers description file "traceur.def"')
    115   CALL msg(fType==2, 'Trying to read the new style multi-sections tracers description file "tracer.def"')
    116   CALL msg(fType==3, 'Trying to read the new style single section tracers description files "tracer_*.def"')
     114  IF (fmsg('No adequate tracers description file(s) found ; default values will be used',          modname, fType==0)) RETURN
     115  CALL msg('Trying to read old-style tracers description file "traceur.def"',                      modname, fType==1)
     116  CALL msg('Trying to read the new style multi-sections tracers description file "tracer.def"',    modname, fType==2)
     117  CALL msg('Trying to read the new style single section tracers description files "tracer_*.def"', modname, fType==3)
    117118
    118119  !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     
    124125    !--- GET THE TRACERS NUMBER
    125126    READ(90,'(i3)',IOSTAT=ierr)ntrac                                 !--- Number of lines/tracers
    126     IF(test(fmsg(ierr /= 0, 'Invalid format for "'//TRIM(fname)//'"'), lerr)) RETURN
     127    IF(test(fmsg('Invalid format for "'//TRIM(fname)//'"', modname, ierr /= 0), lerr)) RETURN
    127128
    128129    !--- READ THE REMAINING LINES: <hadv> <vadv> <tracer> [<transporting fluid>]
     
    130131    DO it=1,ntrac                                                    !=== READ RAW DATA: loop on the line/tracer number
    131132      READ(90,'(a)',IOSTAT=ierr) str
    132       IF(test(fmsg(ierr>0, 'Invalid format for "' //TRIM(fname)//'"'), lerr)) RETURN
    133       IF(test(fmsg(ierr<0, 'Not enough lines in "'//TRIM(fname)//'"'), lerr)) RETURN
     133      IF(test(fmsg('Invalid format for "' //TRIM(fname)//'"', modname, ierr>0), lerr)) RETURN
     134      IF(test(fmsg('Not enough lines in "'//TRIM(fname)//'"', modname, ierr<0), lerr)) RETURN
    134135      ll = strParse(str, ' ', s, n=ns)
    135136      tracs(it)%keys%key = ['hadv', 'vadv']
    136137      tracs(it)%keys%val = s(1:2)
    137       CALL msg(ns == 3 .AND. it == 1, 'This file is for air tracers only')
    138       CALL msg(ns == 4 .AND. it == 1, 'This files specifies the transporting fluid')
    139       tracs(it)%name = s(3); tracs(it)%phas = known_phases(1:1)      !--- Default: name, gazeous phase "g"
     138      CALL msg('This file is for air tracers only',           modname, ns == 3 .AND. it == 1)
     139      CALL msg('This files specifies the transporting fluid', modname, ns == 4 .AND. it == 1)
     140      tracs(it)%name = s(3); tracs(it)%phase = known_phases(1:1)     !--- Default: name, gazeous phase "g"
    140141      DO ip = 1, nphases                                             !--- Deal with old water names
    141142        IF(s(3) /= 'H2O'//old_phases(ip:ip)) CYCLE
    142         tracs(it)%phas = known_phases(ip:ip); tracs(it)%name = 'H2O'//phases_sep//TRIM(tracs(it)%phas)
     143        tracs(it)%phase = known_phases(ip:ip); tracs(it)%name = 'H2O'//phases_sep//TRIM(tracs(it)%phase)
    143144      END DO
    144       tracs(it)%prnt = tran0                                         !--- Default transporting fluid: Air
    145       IF(ns == 4) tracs(it)%prnt = s(4)                              !--- Transporting fluid name
     145      tracs(it)%parent = tran0                                       !--- Default transporting fluid: Air
     146      IF(ns == 4) tracs(it)%parent = s(4)                            !--- Transporting fluid name
    146147    END DO
    147148    CLOSE(90)
    148149
    149     lGen3 = tracs%igen==3
    150     CALL setGeneration(tracs)                                        !--- Determine tracs(:)%igen values
     150    lGen3 = tracs%iGeneration==3
     151    CALL setGeneration(tracs)                                        !--- Determine tracs(:)%iGeneration values
    151152    IF(test(checkTracers(tracs,      fname,fname),lerr)) RETURN      !--- Detect orphans and check phases
    152153    IF(test(checkUnique (tracs,lGen3,fname,fname),lerr)) RETURN      !--- Detect repeated tracers
     
    160161
    161162  !=== USING NEW FORMAT TRACERS DESCRIPTION FILES WITH POSSIBLY SEVERAL SECTIONS
    162   CALL msg(nsec > 1 .AND.      tracs_merge, 'The multiple required sections will be MERGED.')
    163   CALL msg(nsec > 1 .AND. .NOT.tracs_merge, 'The multiple required sections will be CUMULATED.')
     163  CALL msg('The multiple required sections will be MERGED.',    modname, nsec > 1 .AND.      tracs_merge)
     164  CALL msg('The multiple required sections will be CUMULATED.', modname, nsec > 1 .AND. .NOT.tracs_merge)
    164165
    165166  !=== FEED THE DATABASE WITH THE RAW CONTENT OF THE FILE
     
    191192  INTEGER,  ALLOCATABLE :: ixf(:)                                    !--- File index for each section of the expanded list
    192193  LOGICAL,  ALLOCATABLE :: lTg(:)                                    !--- Tagging tracers mask
    193   CHARACTER(LEN=256)    :: fnm, snm
     194  CHARACTER(LEN=maxlen) :: fnm, snm, modname
    194195  INTEGER               :: idb, i
    195196  LOGICAL :: ll
    196197!------------------------------------------------------------------------------------------------------------------------------
    197 
     198  modname = 'feedDBase'
    198199  !=== READ THE REQUIRED SECTIONS
    199200  ll = strCount(snames, ',', ndb)                                    !--- Number of sections for each file
     
    219220
    220221  !=== DISPLAY BASIC INFORMATION
    221   lerr = ANY([(dispTraSection('Expanded list for section "'//TRIM(dBase(idb)%name)//'"',dBase(idb)%name), idb=1, SIZE(dBase))])
     222  lerr = ANY([( dispTraSection('Expanded list for section "'//TRIM(dBase(idb)%name)//'"', dBase(idb)%name, modname), &
     223                idb=1, SIZE(dBase) )])
    222224END FUNCTION feedDBase
    223225!------------------------------------------------------------------------------------------------------------------------------
     
    230232  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: defName                  !--- Special section (default values) name
    231233!------------------------------------------------------------------------------------------------------------------------------
    232   TYPE(db),           ALLOCATABLE :: tdb(:)
    233   CHARACTER(LEN=256), ALLOCATABLE :: sec(:)
    234   INTEGER,            ALLOCATABLE ::  ix(:)
     234  TYPE(dataBase_type),   ALLOCATABLE :: tdb(:)
     235  CHARACTER(LEN=maxlen), ALLOCATABLE :: sec(:)
     236  INTEGER,               ALLOCATABLE ::  ix(:)
    235237  INTEGER :: n0, idb, ndb, i, j
    236238  LOGICAL :: ll
     
    252254SUBROUTINE readSections_all()
    253255!------------------------------------------------------------------------------------------------------------------------------
    254   CHARACTER(LEN=256), ALLOCATABLE ::  s(:), v(:)
    255   TYPE(tra),          ALLOCATABLE :: tt(:)
    256   TYPE(tra)           :: tmp
    257   CHARACTER(LEN=1024) :: str
    258   CHARACTER(LEN=256) :: secn
    259   INTEGER             :: ierr, n
     256  CHARACTER(LEN=maxlen), ALLOCATABLE ::  s(:), v(:)
     257  TYPE(trac_type),       ALLOCATABLE :: tt(:)
     258  TYPE(trac_type)       :: tmp
     259  CHARACTER(LEN=1024)   :: str
     260  CHARACTER(LEN=maxlen) :: secn
     261  INTEGER               :: ierr, n
    260262!------------------------------------------------------------------------------------------------------------------------------
    261263  IF(.NOT.ALLOCATED(dBase)) ALLOCATE(dBase(0))
     
    280282      ll = strParse(str,' ', keys = s, vals = v, n = n)              !--- Parse <key>=<val> pairs
    281283      tt = dBase(ndb)%trac(:)
    282       tmp%name = s(1); tmp%comp=secn; tmp%keys = kys(s(1), s(2:n), v(2:n))
     284      tmp%name = s(1); tmp%component=secn; tmp%keys = keys_type(s(1), s(2:n), v(2:n))
    283285      dBase(ndb)%trac = [tt(:), tmp]
    284286      DEALLOCATE(tt)
    285 !      dBase(ndb)%trac = [dBase(ndb)%trac(:), tra(name=s(1), comp=secn, keys=kys(s(1), s(2:n), v(2:n)))]
     287!      dBase(ndb)%trac = [dBase(ndb)%trac(:), tra(name=s(1), comp=secn, keys=keys_type(s(1), s(2:n), v(2:n)))]
    286288    END IF
    287289  END DO
     
    300302! Purpose: Add the keys from virtual tracer named "defName" (if any) and remove this virtual tracer.
    301303!------------------------------------------------------------------------------------------------------------------------------
    302   TYPE(tra), ALLOCATABLE, TARGET, INTENT(INOUT) :: t(:)
    303   CHARACTER(LEN=*),               INTENT(IN)    :: defName
     304  TYPE(trac_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: t(:)
     305  CHARACTER(LEN=*),                     INTENT(IN)    :: defName
    304306  INTEGER :: jd, it, k
    305   TYPE(kys), POINTER :: ky
    306   TYPE(tra), ALLOCATABLE :: tt(:)
     307  TYPE(keys_type), POINTER :: ky
     308  TYPE(trac_type), ALLOCATABLE :: tt(:)
    307309  jd = strIdx(t(:)%name, defName)
    308310  IF(jd == 0) RETURN
     
    321323!          Substitute the keys locally (for the current tracer) if the flag "lSubLocal" is .TRUE.
    322324!------------------------------------------------------------------------------------------------------------------------------
    323   TYPE(tra), ALLOCATABLE, TARGET, INTENT(INOUT) :: t(:)
    324   CHARACTER(LEN=*),               INTENT(IN)    :: defName
    325   LOGICAL,                        INTENT(IN)    :: lSubLocal
     325  TYPE(trac_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: t(:)
     326  CHARACTER(LEN=*),                     INTENT(IN)    :: defName
     327  LOGICAL,                              INTENT(IN)    :: lSubLocal
    326328  INTEGER :: i0, it, ik
    327   TYPE(kys), POINTER     :: k0, ky
    328   TYPE(tra), ALLOCATABLE :: tt(:)
     329  TYPE(keys_type), POINTER     :: k0, ky
     330  TYPE(trac_type), ALLOCATABLE :: tt(:)
    329331  i0 = strIdx(t(:)%name, defName)
    330332  IF(i0 == 0) RETURN
     
    353355!        * Default values are provided for these keys because they are necessary.
    354356!------------------------------------------------------------------------------------------------------------------------------
    355   TYPE(tra),    ALLOCATABLE, INTENT(INOUT) :: tr(:)                 !--- Tracer derived type vector
    356   CHARACTER(LEN=*),           INTENT(IN)    :: sname
    357   CHARACTER(LEN=*), OPTIONAL, INTENT(IN)    :: fname
    358   TYPE(tra),          ALLOCATABLE :: ttr(:)
    359   CHARACTER(LEN=256), ALLOCATABLE :: ta(:), pa(:)
    360   CHARACTER(LEN=256) :: msg1
     357  TYPE(trac_type), ALLOCATABLE, INTENT(INOUT) :: tr(:)                 !--- Tracer derived type vector
     358  CHARACTER(LEN=*),             INTENT(IN)    :: sname
     359  CHARACTER(LEN=*), OPTIONAL,   INTENT(IN)    :: fname
     360  TYPE(trac_type),       ALLOCATABLE :: ttr(:)
     361  CHARACTER(LEN=maxlen), ALLOCATABLE :: ta(:), pa(:)
     362  CHARACTER(LEN=maxlen) :: msg1, modname
    361363  INTEGER :: it, nt, iq, nq, itr, ntr, ipr, npr, i
    362364  LOGICAL :: ll
     365  modname = 'expandSection'
    363366  lerr = .FALSE.
    364367  nt = SIZE(tr)
     
    368371  !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    369372    !--- Extract useful keys: parent name, type, component name
    370     tr(it)%prnt = fgetKey(it, 'parent', tr(:)%keys,  tran0  )
    371     tr(it)%type = fgetKey(it, 'type'  , tr(:)%keys, 'tracer')
    372     tr(it)%comp = sname
     373    tr(it)%parent    = fgetKey(it, 'parent', tr(:)%keys,  tran0  )
     374    tr(it)%type      = fgetKey(it, 'type'  , tr(:)%keys, 'tracer')
     375    tr(it)%component = sname
    373376
    374377    !--- Determine the number of tracers and parents ; coherence checking
    375     ll = strCount(tr(it)%name, ',', ntr)
    376     ll = strCount(tr(it)%prnt, ',', npr)
     378    ll = strCount(tr(it)%name,   ',', ntr)
     379    ll = strCount(tr(it)%parent, ',', npr)
    377380
    378381    !--- Tagging tracers only can have multiple parents
     
    380383      msg1 = 'Check section "'//TRIM(sname)//'"'
    381384      IF(PRESENT(fname)) msg1=TRIM(msg1)//' in file "'//TRIM(fname)//'"'
    382       CALL msg(TRIM(msg1)//': "'//TRIM(tr(it)%name)//'" has several parents but is not a tag'); RETURN
     385      CALL msg(TRIM(msg1)//': "'//TRIM(tr(it)%name)//'" has several parents but is not a tag', modname); RETURN
    383386    END IF
    384387    nq = nq + ntr*npr                 
     
    394397  !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    395398    ll = strParse(tr(it)%name, ',', ta, n=ntr)                       !--- Number of tracers
    396     ll = strParse(tr(it)%prnt, ',', pa, n=npr)                       !--- Number of parents
     399    ll = strParse(tr(it)%parent, ',', pa, n=npr)                     !--- Number of parents
    397400    DO ipr=1,npr                                                     !--- Loop on parents list elts
    398401      DO itr=1,ntr                                                   !--- Loop on tracers list elts
    399402        i = iq+itr-1+(ipr-1)*ntr
    400         ttr(i)%name = ta(itr); ttr(i)%prnt = pa(ipr)
    401         ttr(i)%keys = kys(ta(itr), tr(it)%keys%key, tr(it)%keys%val)
     403        ttr(i)%name = ta(itr); ttr(i)%parent = pa(ipr)
     404        ttr(i)%keys = keys_type(ta(itr), tr(it)%keys%key, tr(it)%keys%val)
    402405      END DO
    403406    END DO
     
    421424!------------------------------------------------------------------------------------------------------------------------------
    422425! Arguments:
    423   TYPE(tra), INTENT(INOUT) :: tr(:)                                  !--- Tracer derived type vector
     426  TYPE(trac_type), INTENT(INOUT) :: tr(:)                            !--- Tracer derived type vector
    424427!------------------------------------------------------------------------------------------------------------------------------
    425428! Local variables:
    426429  INTEGER :: iq, nq, ig
    427   LOGICAL,            ALLOCATABLE :: lg(:)
    428   CHARACTER(LEN=256), ALLOCATABLE :: prn(:)
    429 !------------------------------------------------------------------------------------------------------------------------------
    430   tr(:)%igen = 0                                                     !--- error if 0
     430  LOGICAL,               ALLOCATABLE :: lg(:)
     431  CHARACTER(LEN=maxlen), ALLOCATABLE :: prn(:)
     432!------------------------------------------------------------------------------------------------------------------------------
     433  tr(:)%iGeneration = 0                                              !--- error if 0
    431434  nq = SIZE(tr, DIM=1)                                               !--- Number of tracers lines
    432   lg = tr(:)%prnt == tran0                                           !--- First generation tracers flag
    433   WHERE(lg) tr(:)%igen = 1                                           !--- First generation tracers
     435  lg = tr(:)%parent == tran0                                         !--- First generation tracers flag
     436  WHERE(lg) tr(:)%iGeneration = 1                                    !--- First generation tracers
    434437
    435438  !=== Determine generation for each tracer
    436439  ig=0; prn = [tran0]
    437440  DO                                                                 !--- Update current generation flag
    438     IF(ig/=0) prn = PACK( tr(:)%name, MASK=tr(:)%igen == ig)
    439     lg(:) = [(ANY(prn(:) == tr(iq)%prnt), iq=1, nq)]                 !--- Current generation tracers flag
     441    IF(ig/=0) prn = PACK( tr(:)%name, MASK=tr(:)%iGeneration == ig)
     442    lg(:) = [(ANY(prn(:) == tr(iq)%parent), iq=1, nq)]               !--- Current generation tracers flag
    440443    IF( ALL( .NOT. lg ) ) EXIT                                       !--- Empty current generation
    441     ig = ig+1; WHERE(lg) tr(:)%igen = ig
    442   END DO
    443   tr(:)%nam1 = ancestor(tr)                                          !--- First generation ancestor name
     444    ig = ig+1; WHERE(lg) tr(:)%iGeneration = ig
     445  END DO
     446  tr(:)%gen0Name = ancestor(tr)                                      !--- First generation ancestor name
    444447
    445448END SUBROUTINE setGeneration
     
    453456!   * check wether the phases are known or not ("g"aseous, "l"iquid or "s"olid so far)
    454457!------------------------------------------------------------------------------------------------------------------------------
    455   TYPE(tra),                  INTENT(IN) :: tr(:)                    !--- Tracer derived type vector
     458  TYPE(trac_type),            INTENT(IN) :: tr(:)                    !--- Tracer derived type vector
    456459  CHARACTER(LEN=*),           INTENT(IN) :: sname                    !--- Section name
    457460  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: fname                    !--- File name
    458   CHARACTER(LEN=256) :: mesg
    459   CHARACTER(LEN=256) :: bp(SIZE(tr, DIM=1)), pha                     !--- Bad phases list, phases of current tracer
     461  CHARACTER(LEN=maxlen) :: mesg
     462  CHARACTER(LEN=maxlen) :: bp(SIZE(tr, DIM=1)), pha                  !--- Bad phases list, phases of current tracer
    460463  CHARACTER(LEN=1) :: p
    461464  INTEGER :: ip, np, iq, nq
     
    466469
    467470  !=== CHECK FOR ORPHAN TRACERS
    468   IF(test(checkList(tr%name, tr%igen==0, mesg, 'tracers', 'orphan'), lerr)) RETURN
     471  IF(test(checkList(tr%name, tr%iGeneration==0, mesg, 'tracers', 'orphan'), lerr)) RETURN
    469472
    470473  !=== CHECK PHASES
    471   DO iq=1,nq; IF(tr(iq)%igen/=1) CYCLE                               !--- Generation 1 only is checked
     474  DO iq=1,nq; IF(tr(iq)%iGeneration/=1) CYCLE                        !--- Generation 1 only is checked
    472475    pha = fgetKey(iq, 'phases', tr(:)%keys, 'g')                     !--- Phases
    473476    np = LEN_TRIM(pha); bp(iq)=' '
     
    475478    IF(TRIM(bp(iq)) /= '') bp(iq) = TRIM(tr(iq)%name)//': '//TRIM(bp(iq))
    476479  END DO
    477   lerr = checkList(bp, tr%igen==1 .AND. bp/='', mesg, 'tracers phases', 'unknown')
     480  lerr = checkList(bp, tr%iGeneration==1 .AND. bp/='', mesg, 'tracers phases', 'unknown')
    478481END FUNCTION checkTracers
    479482!==============================================================================================================================
     
    484487! Purpose: Make sure that tracers are not repeated.
    485488!------------------------------------------------------------------------------------------------------------------------------
    486   TYPE(tra),                  INTENT(IN) :: tr(:)                    !--- Tracer derived type vector
     489  TYPE(trac_type),            INTENT(IN) :: tr(:)                    !--- Tracer derived type vector
    487490  LOGICAL,                    INTENT(IN) :: lTag(:)                  !--- Tagging tracer flag
    488491  CHARACTER(LEN=*),           INTENT(IN) :: sname                    !--- Section name
     
    490493!------------------------------------------------------------------------------------------------------------------------------
    491494  INTEGER :: ip, np, iq, nq, k
    492   LOGICAL, ALLOCATABLE :: ll(:)
    493   CHARACTER(LEN=256) :: mesg, tnam, tdup(SIZE(tr,DIM=1))
    494   CHARACTER(LEN=1)   :: p
     495  LOGICAL, ALLOCATABLE  :: ll(:)
     496  CHARACTER(LEN=maxlen) :: mesg, tnam, tdup(SIZE(tr,DIM=1))
     497  CHARACTER(LEN=1)      :: p
    495498!------------------------------------------------------------------------------------------------------------------------------
    496499  mesg = 'Check section "'//TRIM(sname)//'"'
     
    502505    ll = tr(:)%name==tnam                                            !--- Mask for current tracer name
    503506    IF(COUNT(ll)==1 ) CYCLE                                          !--- Tracer is not repeated
    504     IF(tr(iq)%igen>1) THEN
     507    IF(tr(iq)%iGeneration>1) THEN
    505508      tdup(iq) = tnam                                                !--- gen>1: MUST be unique
    506509    ELSE
     
    524527! Purpose: Expand the phases in the tracers descriptor "tr".
    525528!------------------------------------------------------------------------------------------------------------------------------
    526   TYPE(tra), ALLOCATABLE, INTENT(INOUT) :: tr(:)                     !--- Tracer derived type vector
    527 !------------------------------------------------------------------------------------------------------------------------------
    528   TYPE(tra), ALLOCATABLE :: ttr(:)
    529   INTEGER,  ALLOCATABLE ::  i0(:)
    530   CHARACTER(LEN=256)    :: nam, pha, trn
     529  TYPE(trac_type), ALLOCATABLE, INTENT(INOUT) :: tr(:)               !--- Tracer derived type vector
     530!------------------------------------------------------------------------------------------------------------------------------
     531  TYPE(trac_type), ALLOCATABLE :: ttr(:)
     532  INTEGER,   ALLOCATABLE ::  i0(:)
     533  CHARACTER(LEN=maxlen)  :: nam, pha, trn
    531534  INTEGER :: ip, np, iq, jq, nq, it, nt, nc, i, n
    532535  LOGICAL :: lTg, lEx
     
    535538  nt = 0
    536539  DO iq = 1, nq                                                      !--- GET THE NUMBER OF TRACERS
    537     IF(tr(iq)%igen /= 1) CYCLE
    538     nc = COUNT(tr(:)%nam1==tr(iq)%name .AND. tr%igen/=1)             !--- Number of childs of tr(iq)
    539     tr(iq)%phas = fgetKey(iq, 'phases', tr(:)%keys)                  !--- Phases list      of tr(iq)
    540     np = LEN_TRIM(tr(iq)%phas)                                       !--- Number of phases of tr(iq)
     540    IF(tr(iq)%iGeneration /= 1) CYCLE
     541    nc = COUNT(tr(:)%gen0Name==tr(iq)%name .AND. tr%iGeneration/=1)  !--- Number of childs of tr(iq)
     542    tr(iq)%phase = fgetKey(iq, 'phases', tr(:)%keys)                 !--- Phases list      of tr(iq)
     543    np = LEN_TRIM(tr(iq)%phase)                                      !--- Number of phases of tr(iq)
    541544    nt = nt + (1+nc) * np                                            !--- Number of tracers after expansion
    542545  END DO
     
    545548  DO iq = 1, nq                                                      !--- Loop on "tr(:)" indexes
    546549    lTg = tr(iq)%type=='tag'                                         !--- Current tracer is a tag
    547     i0 = strFind(tr(:)%name, tr(iq)%nam1, n)                         !--- Indexes of first generation ancestor copies
    548     np = SUM( [( LEN_TRIM(tr(i0(i))%phas),i=1,n )],1)                !--- Number of phases for current tracer tr(iq)
     550    i0 = strFind(tr(:)%name, tr(iq)%gen0Name, n)                     !--- Indexes of first generation ancestor copies
     551    np = SUM( [( LEN_TRIM(tr(i0(i))%phase),i=1,n )],1)               !--- Number of phases for current tracer tr(iq)
    549552    lEx = np>1                                                       !--- Need of a phase suffix
    550     IF(lTg) lEx=lEx.AND.tr(iq)%igen>1                                !--- No phase suffix for first generation tags
     553    IF(lTg) lEx=lEx.AND.tr(iq)%iGeneration>1                         !--- No phase suffix for first generation tags
    551554    DO i=1,n                                                         !=== LOOP ON FIRST GENERATION ANCESTORS
    552555      jq=i0(i)                                                       !--- tr(jq): ith copy of 1st gen. ancestor of tr(iq)
    553       IF(tr(iq)%igen==1) jq=iq                                       !--- Generation 1: current tracer phases only
    554       pha = tr(jq)%phas                                              !--- Phases list for tr(jq)
     556      IF(tr(iq)%iGeneration==1) jq=iq                                !--- Generation 1: current tracer phases only
     557      pha = tr(jq)%phase                                             !--- Phases list for tr(jq)
    555558      DO ip=1,LEN_TRIM(pha)                                          !=== LOOP ON PHASES LISTS
    556559        trn=TRIM(tr(iq)%name); nam=trn                               !--- Tracer name (regular case)
    557         IF(lTg) nam = TRIM(tr(iq)%prnt)                              !--- Parent name (tagging case)
     560        IF(lTg) nam = TRIM(tr(iq)%parent)                            !--- Parent name (tagging case)
    558561        IF(lEx) nam = TRIM(nam)//phases_sep//pha(ip:ip)              !--- Phase extension needed
    559562        IF(lTg) nam = TRIM(nam)//'_'//TRIM(trn)                      !--- <parent>_<name> for tags
     
    561564        ttr(it)%name = nam                                           !--- Name with possibly phase suffix
    562565        ttr(it)%keys%name = nam                                      !--- Name inside the keys decriptor
    563         ttr(it)%phas = pha(ip:ip)                                    !--- Single phase entry
    564         IF(lEx.AND.tr(iq)%igen>1) THEN
    565           ttr(it)%prnt = TRIM(ttr(it)%prnt)//phases_sep//pha(ip:ip)
    566           ttr(it)%nam1 = TRIM(ttr(it)%nam1)//phases_sep//pha(ip:ip)
     566        ttr(it)%phase = pha(ip:ip)                                   !--- Single phase entry
     567        IF(lEx.AND.tr(iq)%iGeneration>1) THEN
     568          ttr(it)%parent   = TRIM(ttr(it)%parent)//phases_sep//pha(ip:ip)
     569          ttr(it)%gen0Name = TRIM(ttr(it)%gen0Name)//phases_sep//pha(ip:ip)
    567570        END IF
    568571        it=it+1
    569572      END DO
    570       IF(tr(iq)%igen==1) EXIT                                        !--- Break phase loop for gen 1
     573      IF(tr(iq)%iGeneration==1) EXIT                                 !--- Break phase loop for gen 1
    571574    END DO
    572575  END DO
     
    584587!  * lGrowGen == F: tracer + its childs sorted by growing generation, one after the other.
    585588!------------------------------------------------------------------------------------------------------------------------------
    586   TYPE(tra), ALLOCATABLE, INTENT(INOUT) :: tr(:)                     !--- Tracer derived type vector
     589  TYPE(trac_type), ALLOCATABLE, INTENT(INOUT) :: tr(:)               !--- Tracer derived type vector
    587590  INTEGER :: ig, ng, iq, jq, n, ix(SIZE(tr)), k
    588591  INTEGER, ALLOCATABLE :: iy(:), iz(:)
     
    590593  iq = 1
    591594  IF(lSortByGen) THEN
    592     ng = MAXVAL(tr(:)%igen, MASK=.TRUE., DIM=1)                      !--- Number of generations
     595    ng = MAXVAL(tr(:)%iGeneration, MASK=.TRUE., DIM=1)               !--- Number of generations
    593596    DO ig = 0, ng                                                    !--- Loop on generations
    594       iy = PACK([(k, k=1, SIZE(tr))], MASK=tr(:)%igen==ig)           !--- Generation ig tracers indexes
     597      iy = PACK([(k, k=1, SIZE(tr))], MASK=tr(:)%iGeneration==ig)    !--- Generation ig tracers indexes
    595598      n = SIZE(iy)
    596599      ix(iq:iq+n-1) = iy                                             !--- Stack growing generations idxs
     
    599602  ELSE
    600603    DO jq = 1, SIZE(tr,DIM=1)                                        !--- Loop on first generation tracers
    601       IF(tr(jq)%igen /= 1) CYCLE                                     !--- Skip generations >= 1
     604      IF(tr(jq)%iGeneration /= 1) CYCLE                              !--- Skip generations >= 1
    602605      ix(iq) = jq                                                    !--- First generation ancestor index first
    603606      iq = iq + 1
    604       iy = strFind(tr(:)%nam1, tr(jq)%name)                          !--- Indexes of "tr(jq)" childs in "tr(:)"
    605       ng = MAXVAL(tr(iy)%igen, MASK=.TRUE., DIM=1)                   !--- Generations number of the "tr(jq)" family
     607      iy = strFind(tr(:)%gen0Name, tr(jq)%name)                      !--- Indexes of "tr(jq)" childs in "tr(:)"
     608      ng = MAXVAL(tr(iy)%iGeneration, MASK=.TRUE., DIM=1)            !--- Generations number of the "tr(jq)" family
    606609      DO ig = 2, ng                                                  !--- Loop   on generations for the tr(jq) family
    607         iz = find(tr(iy)%igen, ig, n)                                !--- Indexes of the tracers "tr(iy(:))" of generation "ig"
     610        iz = find(tr(iy)%iGeneration, ig, n)                         !--- Indexes of the tracers "tr(iy(:))" of generation "ig"
    608611        ix(iq:iq+n-1) = iy(iz)                                       !--- Same indexes in "tr(:)"
    609612        iq = iq + n
     
    617620!==============================================================================================================================
    618621LOGICAL FUNCTION mergeTracers(sections, tr) RESULT(lerr)
    619   TYPE(db),  TARGET,      INTENT(IN)  :: sections(:)
    620   TYPE(tra), ALLOCATABLE, INTENT(OUT) ::       tr(:)
    621   TYPE(tra), POINTER    ::   t1(:),   t2(:)
    622   INTEGER,  ALLOCATABLE :: ixct(:), ixck(:)
     622  TYPE(dataBase_type),  TARGET, INTENT(IN)  :: sections(:)
     623  TYPE(trac_type), ALLOCATABLE, INTENT(OUT) ::       tr(:)
     624  TYPE(trac_type), POINTER ::   t1(:),   t2(:)
     625  INTEGER,     ALLOCATABLE :: ixct(:), ixck(:)
    623626  INTEGER :: is, k1, k2, nk2, i1, i2, nt2
    624   CHARACTER(LEN=256) :: s1, v1, v2, tnam, knam
     627  CHARACTER(LEN=maxlen) :: s1, v1, v2, tnam, knam, modname
     628  modname = 'mergeTracers'
    625629  lerr = .FALSE.
    626630  t1 => sections(1)%trac(:)                                          !--- Alias: first tracers section
     
    634638    tr = [tr, PACK(t2, MASK= ixct==0)]                               !--- Append with new tracers
    635639    IF( ALL(ixct == 0) ) CYCLE                                       !--- No common tracers => done
    636     CALL msg('Tracers defined in previous sections and duplicated in "'//TRIM(sections(is)%name)//'":')
    637     CALL msg( t1(PACK(ixct, MASK = ixct/=0))%name, nmax=128 )        !--- Display duplicates (the 128 first at most)
     640    CALL msg('Tracers defined in previous sections and duplicated in "'//TRIM(sections(is)%name)//'":', modname)
     641    CALL msg(t1(PACK(ixct, MASK = ixct/=0))%name, modname, nmax=128) !--- Display duplicates (the 128 first at most)
    638642    !--------------------------------------------------------------------------------------------------------------------------
    639643    DO i2=1,nt2; tnam = t2(i2)%name                                  !=== LOOP ON COMMON TRACERS
     
    644648      s1=' of "'//TRIM(tnam)//'" in "'//TRIM(sections(is)%name)//'" not matching previous value'
    645649     
    646       IF(test(fmsg(t1(i1)%prnt /= t2(i2)%prnt, 'Parent name'//TRIM(s1)), lerr)) RETURN
    647       IF(test(fmsg(t1(i1)%type /= t2(i2)%type, 'Type'       //TRIM(s1)), lerr)) RETURN
    648       IF(test(fmsg(t1(i1)%igen /= t2(i2)%igen, 'Generation' //TRIM(s1)), lerr)) RETURN
     650      IF(test(fmsg('Parent name'//TRIM(s1), modname, t1(i1)%parent      /= t2(i2)%parent),      lerr)) RETURN
     651      IF(test(fmsg('Type'       //TRIM(s1), modname, t1(i1)%type        /= t2(i2)%type),        lerr)) RETURN
     652      IF(test(fmsg('Generation' //TRIM(s1), modname, t1(i1)%iGeneration /= t2(i2)%iGeneration), lerr)) RETURN
    649653
    650654      !=== APPEND <key>=<val> PAIRS NOT PREVIOULSLY DEFINED
     
    657661
    658662      !--- KEEP TRACK OF THE COMPONENTS NAMES
    659       tr(i1)%comp = TRIM(tr(i1)%comp)//','//TRIM(tr(i2)%comp)
     663      tr(i1)%component = TRIM(tr(i1)%component)//','//TRIM(tr(i2)%component)
    660664
    661665      !--- SELECT COMMON TRACERS WITH DIFFERING KEYS VALUES (PREVIOUS VALUE IS KEPT)
     
    667671
    668672      !--- DISPLAY INFORMATION: OLD VALUES ARE KEPT FOR THE KEYS FOUND IN PREVIOUS AND CURRENT SECTIONS
    669       CALL msg('Key(s)'//TRIM(s1))
     673      CALL msg('Key(s)'//TRIM(s1), modname)
    670674      DO k2 = 1, nk2                                                 !--- Loop on keys found in both t1(:) and t2(:)
    671675        knam = t2(i2)%keys%key(k2)                                   !--- Name of the current key
     
    673677        IF(k1 == 0) CYCLE                                            !--- New keys are skipped
    674678        v1 = t1(i1)%keys%val(k1); v2 = t2(i2)%keys%val(k2)           !--- Key values in t1(:) and t2(:)
    675         CALL msg(' * '//TRIM(knam)//'='//TRIM(v2)//' ; previous value kept:'//TRIM(v1))
     679        CALL msg(' * '//TRIM(knam)//'='//TRIM(v2)//' ; previous value kept:'//TRIM(v1), modname)
    676680      END DO
    677681      !------------------------------------------------------------------------------------------------------------------------
     
    686690!==============================================================================================================================
    687691LOGICAL FUNCTION cumulTracers(sections, tr) RESULT(lerr)
    688   TYPE(db),  TARGET,      INTENT(IN)  :: sections(:)
    689   TYPE(tra), ALLOCATABLE, INTENT(OUT) ::       tr(:)
    690   TYPE(tra), POINTER     :: t1(:), t2(:)
     692  TYPE(dataBase_type),  TARGET, INTENT(IN)  :: sections(:)
     693  TYPE(trac_type), ALLOCATABLE, INTENT(OUT) ::       tr(:)
     694  TYPE(trac_type), POINTER     :: t1(:), t2(:)
    691695  INTEGER,   ALLOCATABLE :: nt(:)
    692   CHARACTER(LEN=256)     :: tnam, tnam_new
     696  CHARACTER(LEN=maxlen)  :: tnam, tnam_new
    693697  INTEGER :: iq, nq, is, ns, nsec
    694698  lerr = .FALSE.                                                     !--- Can't fail ; kept to match "mergeTracer" interface.
     
    709713      ns = nt(is)                                                    !--- Number of tracers in the current section
    710714      tr(iq + nq)%name = tnam_new                                    !--- Modify tracer name
    711       WHERE(tr(1+nq:ns+nq)%prnt==tnam) tr(1+nq:ns+nq)%prnt=tnam_new  !--- Modify parent name
     715      WHERE(tr(1+nq:ns+nq)%parent==tnam) tr(1+nq:ns+nq)%parent=tnam_new  !--- Modify parent name
    712716    !--------------------------------------------------------------------------------------------------------------------------
    713717    END DO
     
    721725!==============================================================================================================================
    722726SUBROUTINE setDirectKeys(tr)
    723   TYPE(tra), INTENT(INOUT) :: tr(:)
    724   CALL indexUpdate(tr)                                               !--- Update iparnt and idesc indexes vectors
     727  TYPE(trac_type), INTENT(INOUT) :: tr(:)
     728  CALL indexUpdate(tr)                                               !--- Update iqParent and iqDescen indexes vectors
    725729!  DO iq = 1, SIZE(tr)
    726730!    tr(iq)%keys%<key> = getKey_prv(it, "<key>", tr%keys,  tran0 )   !--- For additional keys
     
    730734
    731735!==============================================================================================================================
    732 LOGICAL FUNCTION dispTraSection(message, sname) RESULT(lerr)
    733   CHARACTER(LEN=*), INTENT(IN) :: message
    734   CHARACTER(LEN=*), INTENT(IN) :: sname
     736LOGICAL FUNCTION dispTraSection(message, sname, modname) RESULT(lerr)
     737  CHARACTER(LEN=*), INTENT(IN) :: message, sname, modname
    735738  INTEGER :: idb, iq, nq
    736739  INTEGER, ALLOCATABLE :: hadv(:), vadv(:)
    737   TYPE(tra), POINTER :: tm(:)
     740  TYPE(trac_type), POINTER :: tm(:)
    738741  lerr = .FALSE.
    739742  idb = strIdx(dBase(:)%name, sname); IF(idb == 0) RETURN
     
    742745  IF(test(getKeyByName_im('hadv', hadv, tm(:)%name, tm(:)%keys),lerr)) RETURN
    743746  IF(test(getKeyByName_im('vadv', vadv, tm(:)%name, tm(:)%keys),lerr)) RETURN
    744   CALL msg(TRIM(message)//':')
     747  CALL msg(TRIM(message)//':', modname)
    745748  IF(test(dispTable('iiissis', ['iq        ','hadv      ','vadv      ','short name','parent    ','igen      ','phase     '], &
    746                     cat(tm(:)%name,  tm(:)%prnt, tm(:)%phas), cat([(iq, iq=1, nq)],  hadv,  vadv, tm(:)%igen)), lerr)) RETURN
     749    cat(tm(:)%name,  tm(:)%parent, tm(:)%phase), cat([(iq, iq=1, nq)],  hadv,  vadv, tm(:)%iGeneration)), lerr)) RETURN
    747750END FUNCTION dispTraSection
    748751!==============================================================================================================================
     
    754757!==============================================================================================================================
    755758FUNCTION aliasTracer(tname, t) RESULT(out)
    756   TYPE(tra),         POINTER    :: out
    757   CHARACTER(LEN=*),  INTENT(IN) :: tname
    758   TYPE(tra), TARGET, INTENT(IN) :: t(:)
     759  TYPE(trac_type),         POINTER    :: out
     760  CHARACTER(LEN=*),        INTENT(IN) :: tname
     761  TYPE(trac_type), TARGET, INTENT(IN) :: t(:)
    759762  INTEGER :: it
    760763  it = strIdx(t(:)%name, tname)
     
    768771!==============================================================================================================================
    769772FUNCTION trSubset_Indx(trac,idx) RESULT(out)
    770   TYPE(tra), ALLOCATABLE             ::  out(:)
    771   TYPE(tra), ALLOCATABLE, INTENT(IN) :: trac(:)
    772   INTEGER,                INTENT(IN) ::  idx(:)
     773  TYPE(trac_type), ALLOCATABLE             ::  out(:)
     774  TYPE(trac_type), ALLOCATABLE, INTENT(IN) :: trac(:)
     775  INTEGER,                      INTENT(IN) ::  idx(:)
    773776  out = trac(idx)
    774777  CALL indexUpdate(out)
     
    776779!------------------------------------------------------------------------------------------------------------------------------
    777780FUNCTION trSubset_Name(trac,nam) RESULT(out)
    778   TYPE(tra), ALLOCATABLE             ::  out(:)
    779   TYPE(tra), ALLOCATABLE, INTENT(IN) :: trac(:)
    780   CHARACTER(LEN=*),       INTENT(IN) ::  nam(:)
     781  TYPE(trac_type), ALLOCATABLE             ::  out(:)
     782  TYPE(trac_type), ALLOCATABLE, INTENT(IN) :: trac(:)
     783  CHARACTER(LEN=*),             INTENT(IN) ::  nam(:)
    781784  out = trac(strIdx(trac(:)%name, nam))
    782785  CALL indexUpdate(out)
     
    788791!=== CREATE THE SUBSET OF THE TRACERS DESCRIPTORS LIST "trac" HAVING THE FIRST GENERATION ANCESTOR NAMED "nam" ================
    789792!==============================================================================================================================
    790 FUNCTION trSubset_Nam1(trac,nam) RESULT(out)
    791   TYPE(tra), ALLOCATABLE             ::  out(:)
    792   TYPE(tra), ALLOCATABLE, INTENT(IN) :: trac(:)
    793   CHARACTER(LEN=*),       INTENT(IN) ::  nam
    794   out = trac(strFind(delPhase(trac(:)%nam1), nam))
     793FUNCTION trSubset_gen0Name(trac,nam) RESULT(out)
     794  TYPE(trac_type), ALLOCATABLE             ::  out(:)
     795  TYPE(trac_type), ALLOCATABLE, INTENT(IN) :: trac(:)
     796  CHARACTER(LEN=*),             INTENT(IN) ::  nam
     797  out = trac(strFind(delPhase(trac(:)%gen0Name), nam))
    795798  CALL indexUpdate(out)
    796 END FUNCTION trSubset_Nam1
    797 !------------------------------------------------------------------------------------------------------------------------------
    798 
    799 
    800 !==============================================================================================================================
    801 !=== UPDATE THE INDEXES iparnt(:), idesc=(:) AND igen(:) IN THE TRACERS DESCRIPTOR LIST "tr" (USEFULL FOR SUBSETS) ============
     799END FUNCTION trSubset_gen0Name
     800!------------------------------------------------------------------------------------------------------------------------------
     801
     802
     803!==============================================================================================================================
     804!=== UPDATE THE INDEXES iqParent, iqDescend AND iGeneration IN THE TRACERS DESCRIPTOR LIST "tr" (USEFULL FOR SUBSETS) =========
    802805!==============================================================================================================================
    803806SUBROUTINE indexUpdate(tr)
    804   TYPE(tra), INTENT(INOUT) :: tr(:)
     807  TYPE(trac_type), INTENT(INOUT) :: tr(:)
    805808  INTEGER :: iq, ig, ng, ngen
    806809  INTEGER, ALLOCATABLE :: ix(:)
    807   tr(:)%iprnt = strIdx( tr(:)%name, tr(:)%prnt )                     !--- Parent index
    808   ngen = MAXVAL(tr(:)%igen, MASK=.TRUE.)
     810  tr(:)%iqParent = strIdx( tr(:)%name, tr(:)%parent )                !--- Parent index
     811  ngen = MAXVAL(tr(:)%iGeneration, MASK=.TRUE.)
    809812  DO iq = 1, SIZE(tr)
    810     ng = tr(iq)%igen                                                 !--- Generation of the current tracer
     813    ng = tr(iq)%iGeneration                                          !--- Generation of the current tracer
    811814    ix = idxAncestor(tr, igen = ng); ix = PACK(ix, ix/=0)            !--- Indexes of the tracers with ancestor tr(iq)
    812815    !--- Childs indexes in growing generation order
    813     tr(iq)%idesc = [( PACK(ix, MASK = tr(ix)%igen == ig), ig = ng+1, ngen)]
    814     tr(iq)%ndesc =     SUM(  [( COUNT(tr(ix)%igen == ig), ig = ng+1, ngen)] )
    815     tr(iq)%nchld =              COUNT(tr(ix)%igen == ng+1)
     816    tr(iq)%iqDescen = [( PACK(ix, MASK = tr(ix)%iGeneration == ig), ig = ng+1, ngen)]
     817    tr(iq)%nqDescen =     SUM(  [( COUNT(tr(ix)%iGeneration == ig), ig = ng+1, ngen)] )
     818    tr(iq)%nqChilds =              COUNT(tr(ix)%iGeneration == ng+1)
    816819  END DO
    817820END SUBROUTINE indexUpdate
     
    820823 
    821824!==============================================================================================================================
    822 !=== READ FILE "fnam" TO APPEND THE "dBase" TRACERS DATABASE WITH AS MUCH SECTIONS AS PARENTS NAMES IN "isot(:)%prnt":     ====
    823 !===  * Each section dBase(i)%name contains the isotopes "dBase(i)%trac(:)" descending on "dBase(i)%name"="iso(i)%prnt"    ====
     825!=== READ FILE "fnam" TO APPEND THE "dBase" TRACERS DATABASE WITH AS MUCH SECTIONS AS PARENTS NAMES IN "isot(:)%parent":   ====
     826!===  * Each section dBase(i)%name contains the isotopes "dBase(i)%trac(:)" descending on "dBase(i)%name"="iso(i)%parent"  ====
    824827!===  * For each isotopes class, the <key>=<val> vector of each tracer is moved into the isotopes descriptor "isot"        ====
    825828!=== NOTES:                                                                                                                ====
     
    833836!==============================================================================================================================
    834837LOGICAL FUNCTION readIsotopesFile(fnam, isot) RESULT(lerr)
    835   CHARACTER(LEN=*),  INTENT(IN)    :: fnam                           !--- Input file name
    836   TYPE(iso), TARGET, INTENT(INOUT) :: isot(:)                        !--- Isotopes descriptors (field "prnt" must be defined !)
     838  CHARACTER(LEN=*),        INTENT(IN)    :: fnam                     !--- Input file name
     839  TYPE(isot_type), TARGET, INTENT(INOUT) :: isot(:)                  !--- Isotopes descriptors (field "prnt" must be defined !)
    837840  INTEGER :: ik, is, it, idb, nk0, i, iis
    838841  INTEGER :: nk, ns, nt, ndb, nb0, i0
    839   CHARACTER(LEN=256), POINTER     :: k(:), v(:), k0(:), v0(:)
    840   CHARACTER(LEN=256), ALLOCATABLE :: vals(:)
    841   CHARACTER(LEN=256)     :: val
    842   TYPE(kys),    POINTER  ::   ky(:)
    843   TYPE(tra),    POINTER  ::   tt(:), t
    844   TYPE(db),  ALLOCATABLE ::  tdb(:)
    845   LOGICAL,   ALLOCATABLE :: liso(:)
     842  CHARACTER(LEN=maxlen), POINTER     :: k(:), v(:), k0(:), v0(:)
     843  CHARACTER(LEN=maxlen), ALLOCATABLE :: vals(:)
     844  CHARACTER(LEN=maxlen)              :: val, modname
     845  TYPE(keys_type),           POINTER ::   ky(:)
     846  TYPE(trac_type),           POINTER ::   tt(:), t
     847  TYPE(dataBase_type),   ALLOCATABLE ::  tdb(:)
     848  LOGICAL,               ALLOCATABLE :: liso(:)
     849  modname = 'readIsotopesFile'
    846850
    847851  !--- THE INPUT FILE MUST BE PRESENT
    848   IF(test(fmsg(testFile(fnam),'Missing isotopes parameters file "'//TRIM(fnam)//'"'),lerr)) RETURN
     852  IF(test(fmsg('Missing isotopes parameters file "'//TRIM(fnam)//'"', modname, testFile(fnam)),lerr)) RETURN
    849853
    850854  !--- READ THE FILE SECTIONS, ONE EACH PARENT TRACER
    851855  nb0 = SIZE(dBase, DIM=1)+1                                         !--- Next database element index
    852   IF(test(readSections(fnam,strStack(isot(:)%prnt,',')),lerr)) RETURN!--- Read sections, one each parent tracer
     856  IF(test(readSections(fnam,strStack(isot(:)%parent,',')),lerr)) RETURN !--- Read sections, one each parent tracer
    853857  ndb = SIZE(dBase, DIM=1)                                           !--- Current database size
    854858  DO idb = nb0, ndb
     
    886890    ALLOCATE(tdb(nb0-1)); tdb(1:nb0-1)=dBase(1:nb0-1); CALL MOVE_ALLOC(FROM=tdb, TO=dBase)
    887891  END IF
    888   lerr = dispIsotopes(isot, 'Isotopes parameters read from file')
     892  lerr = dispIsotopes(isot, 'Isotopes parameters read from file', modname)
    889893
    890894END FUNCTION readIsotopesFile
     
    899903!==============================================================================================================================
    900904SUBROUTINE initIsotopes(trac, isot)
    901   TYPE(tra), ALLOCATABLE, TARGET, INTENT(INOUT) :: trac(:)
    902   TYPE(iso), ALLOCATABLE, TARGET, INTENT(INOUT) :: isot(:)
    903   CHARACTER(LEN=256), ALLOCATABLE :: p(:), str(:)                    !--- Temporary storage
    904   CHARACTER(LEN=256) :: iname
     905  TYPE(trac_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: trac(:)
     906  TYPE(isot_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: isot(:)
     907  CHARACTER(LEN=maxlen), ALLOCATABLE :: p(:), str(:)                 !--- Temporary storage
     908  CHARACTER(LEN=maxlen) :: iname
    905909  CHARACTER(LEN=1)   :: ph                                           !--- Phase
    906910  INTEGER :: nbIso, ic, ip, iq, it, iz
    907911  LOGICAL, ALLOCATABLE :: ll(:)                                      !--- Mask
    908   TYPE(tra), POINTER   ::  t(:), t1
    909   TYPE(iso), POINTER   ::  s
     912  TYPE(trac_type), POINTER   ::  t(:), t1
     913  TYPE(isot_type), POINTER   ::  s
    910914
    911915  t => trac
    912916
    913   p = PACK(delPhase(t%prnt), MASK = t%type=='tracer' .AND. t%igen==2)!--- Parents of 2nd generation isotopes
     917  p = PACK(delPhase(t%parent), MASK = t%type=='tracer' .AND. t%iGeneration==2) !--- Parents of 2nd generation isotopes
    914918  CALL strReduce(p, nbIso)
    915919  ALLOCATE(isot(nbIso))
     
    918922
    919923  !--- ISOTOPES RELATED VARIABLES ; NULL OR EMPTY IF NO ISOTOPES
    920   isot(:)%prnt = p
     924  isot(:)%parent = p
    921925  DO ic = 1, SIZE(p)                                                 !--- Loop on isotopes classes
    922926    s => isot(ic)
    923     iname = s%prnt                                                   !--- Current isotopes class name (parent tracer name)
     927    iname = s%parent                                                 !--- Current isotopes class name (parent tracer name)
    924928
    925929    !=== Isotopes childs of tracer "iname": mask, names, number (same for each phase of "iname")
    926     ll = t(:)%type=='tracer' .AND. delPhase(t(:)%prnt) == iname .AND. t(:)%phas == 'g'
     930    ll = t(:)%type=='tracer' .AND. delPhase(t(:)%parent) == iname .AND. t(:)%phase == 'g'
    927931    str = PACK(delPhase(t(:)%name), MASK = ll)                       !--- Effectively found isotopes of "iname"
    928932    s%niso = SIZE(str)                                               !--- Number of "effectively found isotopes of "iname"
     
    931935
    932936    !=== Geographic tagging tracers descending on tracer "iname": mask, names, number
    933     ll = t(:)%type=='tag'    .AND. delPhase(t(:)%nam1) == iname .AND. t(:)%igen == 3
     937    ll = t(:)%type=='tag'    .AND. delPhase(t(:)%gen0Name) == iname .AND. t(:)%iGeneration == 3
    934938    s%zone = PACK(strTail(t(:)%name,'_',lFirst=.TRUE.), MASK = ll)   !--- Tagging zones names  for isotopes category "iname"
    935939    CALL strReduce(s%zone)
     
    946950
    947951    !=== Phases for tracer "iname"
    948     s%phas = ''
    949     DO ip = 1, nphases; ph = known_phases(ip:ip); IF(strIdx(t%name,addPhase(iname, ph)) /= 0) s%phas = TRIM(s%phas)//ph; END DO
    950     s%npha = LEN_TRIM(s%phas)                                        !--- Equal to "nqo" for water
     952    s%phase = ''
     953    DO ip = 1, nphases; ph = known_phases(ip:ip); IF(strIdx(t%name,addPhase(iname, ph)) /= 0) s%phase = TRIM(s%phase)//ph; END DO
     954    s%npha = LEN_TRIM(s%phase)                                        !--- Equal to "nqo" for water
    951955
    952956    !=== Tables giving the index in a table of effectively found items for each dynamical tracer (1<=iq<=nqtot)
    953957    DO iq = 1, SIZE(t)
    954958      t1 => trac(iq)
    955       IF(delPhase(t1%nam1) /= iname) CYCLE                            !--- Only deal with tracers descending on "iname"
    956       t1%iso_igr = ic                                                 !--- Isotopes family       idx in list "isotopes(:)%prnt"
    957       t1%iso_num = strIdx(s%trac, delPhase(strHead(t1%name,'_')))    !--- Current isotope       idx in effective isotopes list
    958       t1%iso_zon = strIdx(s%zone,          strTail(t1%name,'_') )    !--- Current isotope zone  idx in effective zones    list
    959       t1%iso_pha =  INDEX(s%phas,TRIM(t1%phas))                       !--- Current isotope phase idx in effective phases   list
    960       IF(t1%igen /= 3) t1%iso_zon = 0                                 !--- Skip possible generation 2 tagging tracers
     959      IF(delPhase(t1%gen0Name) /= iname) CYCLE                       !--- Only deal with tracers descending on "iname"
     960      t1%iso_iGroup = ic                                             !--- Isotopes family       idx in list "isotopes(:)%parent"
     961      t1%iso_iName  = strIdx(s%trac, delPhase(strHead(t1%name,'_'))) !--- Current isotope       idx in effective isotopes list
     962      t1%iso_iZone  = strIdx(s%zone,          strTail(t1%name,'_') ) !--- Current isotope zone  idx in effective zones    list
     963      t1%iso_iPhase =  INDEX(s%phase,TRIM(t1%phase))                 !--- Current isotope phase idx in effective phases   list
     964      IF(t1%iGeneration /= 3) t1%iso_iZone = 0                       !--- Skip possible generation 2 tagging tracers
    961965    END DO
    962966
    963967    !=== Table used to get iq (index in dyn array, size nqtot) from the isotope and phase indexes ; the full isotopes list
    964968    !    (including tagging tracers) is sorted this way:  iso1, iso2, ..., iso1_zone1, iso2_zone1, ..., iso1_zoneN, iso2_zoneN
    965     s%iTraPha = RESHAPE( [( (strIdx(t(:)%name,  addPhase(s%trac(it),s%phas(ip:ip))),     it=1, s%nitr), ip=1, s%npha)], &
     969    s%iTraPha = RESHAPE( [( (strIdx(t(:)%name,  addPhase(s%trac(it),s%phase(ip:ip))),    it=1, s%nitr), ip=1, s%npha)], &
    966970                         [s%nitr, s%npha] )
    967971
     
    970974                         [s%nzon, s%niso] )
    971975  END DO
    972  
    973   !=== Indexes, in dynamical tracers list, of the tracers transmitted to phytrac (nqtottr non-vanishing elements)
    974   ll = delPhase(t%name)/='H2O' .AND. t%iso_num ==0              !--- Mask of tracers passed to the physics
    975   t(:)%itr = UNPACK([(iq,iq=1,COUNT(ll))], ll, [(0, iq=1, SIZE(t))])
    976976
    977977  !=== READ PHYSICAL PARAMETERS FROM "isotopes_params.def" FILE
     
    984984
    985985!==============================================================================================================================
    986 LOGICAL FUNCTION dispIsotopes(ides, message) RESULT(lerr)
    987   TYPE(iso),        INTENT(IN) :: ides(:)                            !--- Isotopes descriptor vector
     986LOGICAL FUNCTION dispIsotopes(ides, message, modname) RESULT(lerr)
     987  TYPE(isot_type),  INTENT(IN) :: ides(:)                            !--- Isotopes descriptor vector
    988988  CHARACTER(LEN=*), INTENT(IN) :: message                            !--- Message to display
     989  CHARACTER(LEN=*), INTENT(IN) :: modname                            !--- Calling subroutine name
    989990  INTEGER :: ik, nk, ip, it, nt
    990   CHARACTER(LEN=256) :: prf
    991   CHARACTER(LEN=256), ALLOCATABLE :: ttl(:), val(:,:)
    992   CALL msg(TRIM(message)//':')
     991  CHARACTER(LEN=maxlen) :: prf
     992  CHARACTER(LEN=maxlen), ALLOCATABLE :: ttl(:), val(:,:)
     993  CALL msg(TRIM(message)//':', modname)
    993994  DO ip = 1, SIZE(ides)                                              !--- Loop on parents tracers
    994995    nk = SIZE(ides(ip)%keys(1)%key)                                  !--- Same keys for each isotope
     
    10031004      END DO
    10041005    END DO
    1005     IF(test(fmsg(dispTable(prf, ttl, val, cat([(it,it=1,nt)]), rFmt='(EN8.4)'),'Problem with the table content'), lerr)) RETURN
     1006    IF(test(fmsg('Problem with the table content', modname, dispTable(prf, ttl, val, cat([(it,it=1,nt)]), rFmt='(EN8.4)')), &
     1007       lerr)) RETURN
    10061008    DEALLOCATE(ttl, val)
    10071009  END DO       
     
    10161018!------------------------------------------------------------------------------------------------------------------------------
    10171019  CHARACTER(LEN=*),  INTENT(IN)    :: key, val
    1018   TYPE(kys),         INTENT(INOUT) :: ky
     1020  TYPE(keys_type),   INTENT(INOUT) :: ky
    10191021  LOGICAL, OPTIONAL, INTENT(IN)    :: lOverWrite
    1020   CHARACTER(LEN=256), ALLOCATABLE :: k(:), v(:)
     1022  CHARACTER(LEN=maxlen), ALLOCATABLE :: k(:), v(:)
    10211023  INTEGER :: iky, nky
    10221024  LOGICAL :: lo
     
    10371039!------------------------------------------------------------------------------------------------------------------------------
    10381040  CHARACTER(LEN=*),  INTENT(IN)    :: key, val
    1039   TYPE(kys),         INTENT(INOUT) :: ky(:)
     1041  TYPE(keys_type),   INTENT(INOUT) :: ky(:)
    10401042  LOGICAL, OPTIONAL, INTENT(IN)    :: lOverWrite
    10411043  INTEGER :: itr
     
    10501052! Purpose: The values of the keys of the tracer named "tr0" are overwritten by the values found in the *.def files, if any.
    10511053!------------------------------------------------------------------------------------------------------------------------------
    1052   TYPE(tra), ALLOCATABLE, INTENT(INOUT) :: t(:)
    1053   CHARACTER(LEN=*),       INTENT(IN)    :: tr0
    1054   CHARACTER(LEN=256) :: val
    1055   INTEGER            :: ik, jd
     1054  TYPE(trac_type), ALLOCATABLE, INTENT(INOUT) :: t(:)
     1055  CHARACTER(LEN=*),             INTENT(IN)    :: tr0
     1056  CHARACTER(LEN=maxlen) :: val
     1057  INTEGER               :: ik, jd
    10561058  jd = strIdx(t%name, tr0)
    10571059  IF(jd == 0) RETURN
     
    10691071  INTEGER,          INTENT(IN)    :: itr
    10701072  CHARACTER(LEN=*), INTENT(IN)    :: keyn(:)
    1071   TYPE(tra),        INTENT(INOUT) :: ky(:)
    1072   CHARACTER(LEN=256), ALLOCATABLE :: k(:), v(:)
    1073   LOGICAL,  ALLOCATABLE :: ll(:)
     1073  TYPE(trac_type),  INTENT(INOUT) :: ky(:)
     1074  CHARACTER(LEN=maxlen), ALLOCATABLE :: k(:), v(:)
     1075  LOGICAL,               ALLOCATABLE :: ll(:)
    10741076  INTEGER :: iky
    10751077!------------------------------------------------------------------------------------------------------------------------------
     
    10861088!------------------------------------------------------------------------------------------------------------------------------
    10871089  CHARACTER(LEN=*), INTENT(IN)    :: keyn(:)
    1088   TYPE(tra),        INTENT(INOUT) :: ky(:)
     1090  TYPE(trac_type),  INTENT(INOUT) :: ky(:)
    10891091  INTEGER :: iky
    10901092!------------------------------------------------------------------------------------------------------------------------------
     
    11001102!==============================================================================================================================
    11011103SUBROUTINE getKey_init(tracers_, isotopes_)
    1102   TYPE(tra), OPTIONAL, INTENT(IN) ::  tracers_(:)
    1103   TYPE(iso), OPTIONAL, INTENT(IN) :: isotopes_(:)
     1104  TYPE(trac_type), OPTIONAL, INTENT(IN) ::  tracers_(:)
     1105  TYPE(isot_type), OPTIONAL, INTENT(IN) :: isotopes_(:)
    11041106  IF(PRESENT( tracers_))  tracers =  tracers_
    11051107  IF(PRESENT(isotopes_)) isotopes = isotopes_
    11061108END SUBROUTINE getKey_init
    11071109!==============================================================================================================================
    1108 CHARACTER(LEN=256) FUNCTION fgetKey(itr, keyn, ky, def_val) RESULT(out)
     1110CHARACTER(LEN=maxlen) FUNCTION fgetKey(itr, keyn, ky, def_val) RESULT(out)
    11091111!------------------------------------------------------------------------------------------------------------------------------
    11101112! Purpose: Internal function ; get a key value in string format (this is the returned argument).
     
    11121114  INTEGER,                    INTENT(IN) :: itr
    11131115  CHARACTER(LEN=*),           INTENT(IN) :: keyn
    1114   TYPE(kys),                  INTENT(IN) :: ky(:)
     1116  TYPE(keys_type),            INTENT(IN) :: ky(:)
    11151117  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: def_val
    11161118!------------------------------------------------------------------------------------------------------------------------------
     
    11261128  !     * "ky"   specified: try in "ky"      for "tnam" with phase and tagging suffixes, then without.
    11271129  !    The returned error code is always .FALSE.: an empty string is returned when the key hasn't been found.
    1128   CHARACTER(LEN=*),    INTENT(IN)  :: keyn
    1129   CHARACTER(LEN=256),  INTENT(OUT) :: val
    1130   CHARACTER(LEN=*),    INTENT(IN)  :: tname
    1131   TYPE(kys), OPTIONAL, INTENT(IN)  :: ky(:)
     1130  CHARACTER(LEN=*),          INTENT(IN)  :: keyn
     1131  CHARACTER(LEN=maxlen),     INTENT(OUT) :: val
     1132  CHARACTER(LEN=*),          INTENT(IN)  :: tname
     1133  TYPE(keys_type), OPTIONAL, INTENT(IN)  :: ky(:)
    11321134  INTEGER :: is
    11331135  lerr = .FALSE.
     
    11471149
    11481150FUNCTION getKeyByName_prv(keyn, tname, ky) RESULT(val)
    1149   CHARACTER(LEN=256)            :: val
     1151  CHARACTER(LEN=maxlen)         :: val
    11501152  CHARACTER(LEN=*), INTENT(IN)  :: keyn
    11511153  CHARACTER(LEN=*), INTENT(IN)  :: tname
    1152   TYPE(kys),        INTENT(IN)  :: ky(:)
     1154  TYPE(keys_type),  INTENT(IN)  :: ky(:)
    11531155  INTEGER :: itr, iky
    11541156  val = ''; iky = 0
     
    11621164LOGICAL FUNCTION getKeyByName_sm(keyn, val, tnam, ky) RESULT(lerr)
    11631165  CHARACTER(LEN=*),                   INTENT(IN)  :: keyn
    1164   CHARACTER(LEN=256),    ALLOCATABLE, INTENT(OUT) ::  val(:)
     1166  CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) ::  val(:)
    11651167  CHARACTER(LEN=*), TARGET, OPTIONAL, INTENT(IN)  :: tnam(:)
    1166   TYPE(kys),        TARGET, OPTIONAL, INTENT(IN)  ::   ky(:)
    1167   CHARACTER(LEN=256), POINTER :: n(:)
     1168  TYPE(keys_type),  TARGET, OPTIONAL, INTENT(IN)  ::   ky(:)
     1169  CHARACTER(LEN=maxlen),    POINTER :: n(:)
    11681170  INTEGER :: iq
    11691171  n => tracers(:)%keys%name; IF(PRESENT(tnam)) n => tnam(:)
     
    11741176!==============================================================================================================================
    11751177LOGICAL FUNCTION getKeyByName_i1(keyn, val, tnam, ky) RESULT(lerr)
    1176   CHARACTER(LEN=*),    INTENT(IN)  :: keyn
    1177   INTEGER,             INTENT(OUT) :: val
    1178   CHARACTER(LEN=*),    INTENT(IN)  :: tnam
    1179   TYPE(kys), OPTIONAL, INTENT(IN)  :: ky(:)
    1180   CHARACTER(LEN=256) :: sval
     1178  CHARACTER(LEN=*),          INTENT(IN)  :: keyn
     1179  INTEGER,                   INTENT(OUT) :: val
     1180  CHARACTER(LEN=*),          INTENT(IN)  :: tnam
     1181  TYPE(keys_type), OPTIONAL, INTENT(IN)  :: ky(:)
     1182  CHARACTER(LEN=maxlen) :: sval
    11811183  INTEGER :: ierr
    11821184  IF(     PRESENT(ky)) lerr = getKeyByName_s1(keyn, sval, tnam, ky)
    11831185  IF(.NOT.PRESENT(ky)) lerr = getKeyByName_s1(keyn, sval, tnam)
    1184   IF(test(fmsg(lerr,   'key "'//TRIM(keyn)//'" or tracer "'//TRIM(tnam)//'" is missing'),        lerr)) RETURN
     1186  IF(test(fmsg('key "'//TRIM(keyn)//'" or tracer "'//TRIM(tnam)//'" is missing',        modname, lerr), lerr)) RETURN
    11851187  READ(sval, *, IOSTAT=ierr) val
    1186   IF(test(fmsg(ierr/=0,'key "'//TRIM(keyn)//'" of tracer "'//TRIM(tnam)//'" is not an integer'), lerr)) RETURN
     1188  IF(test(fmsg('key "'//TRIM(keyn)//'" of tracer "'//TRIM(tnam)//'" is not an integer', modname, lerr), lerr)) RETURN
    11871189END FUNCTION getKeyByName_i1
    11881190!==============================================================================================================================
     
    11911193  INTEGER,               ALLOCATABLE, INTENT(OUT) ::  val(:)
    11921194  CHARACTER(LEN=*), TARGET, OPTIONAL, INTENT(IN)  :: tnam(:)
    1193   TYPE(kys),        TARGET, OPTIONAL, INTENT(IN)  ::   ky(:)
    1194   CHARACTER(LEN=256), POINTER :: n(:)
     1195  TYPE(keys_type),  TARGET, OPTIONAL, INTENT(IN)  ::   ky(:)
     1196  CHARACTER(LEN=maxlen), POINTER :: n(:)
    11951197  INTEGER :: iq
    11961198  n => tracers(:)%name; IF(PRESENT(tnam)) n => tnam(:)
     
    12011203!==============================================================================================================================
    12021204LOGICAL FUNCTION getKeyByName_r1(keyn, val, tnam, ky) RESULT(lerr)
    1203   CHARACTER(LEN=*),    INTENT(IN)  :: keyn
    1204   REAL,                INTENT(OUT) :: val
    1205   CHARACTER(LEN=*),    INTENT(IN)  :: tnam
    1206   TYPE(kys), OPTIONAL, INTENT(IN)  :: ky(:)
    1207   CHARACTER(LEN=256) :: sval
     1205  CHARACTER(LEN=*),          INTENT(IN)  :: keyn
     1206  REAL,                      INTENT(OUT) :: val
     1207  CHARACTER(LEN=*),          INTENT(IN)  :: tnam
     1208  TYPE(keys_type), OPTIONAL, INTENT(IN)  :: ky(:)
     1209  CHARACTER(LEN=maxlen) :: sval
    12081210  INTEGER :: ierr
    12091211  IF(     PRESENT(ky)) lerr = getKeyByName_s1(keyn, sval, tnam, ky)
    12101212  IF(.NOT.PRESENT(ky)) lerr = getKeyByName_s1(keyn, sval, tnam)
    1211   IF(test(fmsg(lerr,   'key "'//TRIM(keyn)//'" or tracer "'//TRIM(tnam)//'" is missing'),    lerr)) RETURN
     1213  IF(test(fmsg('key "'//TRIM(keyn)//'" or tracer "'//TRIM(tnam)//'" is missing',    modname, lerr), lerr)) RETURN
    12121214  READ(sval, *, IOSTAT=ierr) val
    1213   IF(test(fmsg(ierr/=0,'key "'//TRIM(keyn)//'" of tracer "'//TRIM(tnam)//'" is not a real'), lerr)) RETURN
     1215  IF(test(fmsg('key "'//TRIM(keyn)//'" of tracer "'//TRIM(tnam)//'" is not a real', modname, lerr), lerr)) RETURN
    12141216END FUNCTION getKeyByName_r1
    12151217!==============================================================================================================================
     
    12181220  REAL,                  ALLOCATABLE, INTENT(OUT) ::  val(:)
    12191221  CHARACTER(LEN=*), TARGET, OPTIONAL, INTENT(IN)  :: tnam(:)
    1220   TYPE(kys),        TARGET, OPTIONAL, INTENT(IN)  ::   ky(:)
    1221   CHARACTER(LEN=256), POINTER :: n(:)
     1222  TYPE(keys_type),  TARGET, OPTIONAL, INTENT(IN)  ::   ky(:)
     1223  CHARACTER(LEN=maxlen), POINTER :: n(:)
    12221224  INTEGER :: iq
    12231225  n => tracers(:)%name;  IF(PRESENT(tnam)) n => tnam(:)
     
    12321234!=== REMOVE, IF ANY, OR ADD THE PHASE SUFFIX OF THE TRACER NAMED "s" ==========================================================
    12331235!==============================================================================================================================
    1234 ELEMENTAL CHARACTER(LEN=256) FUNCTION delPhase(s) RESULT(out)
     1236ELEMENTAL CHARACTER(LEN=maxlen) FUNCTION delPhase(s) RESULT(out)
    12351237  CHARACTER(LEN=*), INTENT(IN) :: s
    12361238  INTEGER :: l, i, ix
     
    12491251END FUNCTION delPhase
    12501252!------------------------------------------------------------------------------------------------------------------------------
    1251 CHARACTER(LEN=256) FUNCTION addPhase_1(s,pha) RESULT(out)
     1253CHARACTER(LEN=maxlen) FUNCTION addPhase_1(s,pha) RESULT(out)
    12521254  CHARACTER(LEN=*), INTENT(IN) :: s
    12531255  CHARACTER(LEN=1), INTENT(IN) :: pha
     
    12621264!------------------------------------------------------------------------------------------------------------------------------
    12631265FUNCTION addPhase_m(s,pha) RESULT(out)
    1264   CHARACTER(LEN=*),    INTENT(IN) :: s(:)
    1265   CHARACTER(LEN=1),    INTENT(IN) :: pha
    1266   CHARACTER(LEN=256), ALLOCATABLE :: out(:) 
     1266  CHARACTER(LEN=*),      INTENT(IN) :: s(:)
     1267  CHARACTER(LEN=1),      INTENT(IN) :: pha
     1268  CHARACTER(LEN=maxlen), ALLOCATABLE :: out(:) 
    12671269  INTEGER :: k
    12681270  out = [( addPhase_1(s(k), pha), k=1, SIZE(s) )]
     
    12741276!=== GET THE NAME(S) OF THE ANCESTOR(S) OF TRACER(S) "tname" AT GENERATION "igen"  IN THE TRACERS DESCRIPTORS LIST "tr" =======
    12751277!==============================================================================================================================
    1276 CHARACTER(LEN=256) FUNCTION ancestor_1(t, tname, igen) RESULT(out)
    1277   TYPE(tra),         INTENT(IN) :: t(:)
     1278CHARACTER(LEN=maxlen) FUNCTION ancestor_1(t, tname, igen) RESULT(out)
     1279  TYPE(trac_type),   INTENT(IN) :: t(:)
    12781280  CHARACTER(LEN=*),  INTENT(IN) :: tname
    12791281  INTEGER, OPTIONAL, INTENT(IN) :: igen
     
    12851287!------------------------------------------------------------------------------------------------------------------------------
    12861288FUNCTION ancestor_m(t, tname, igen) RESULT(out)
    1287   CHARACTER(LEN=256), ALLOCATABLE        ::   out(:)
    1288   TYPE(tra),                  INTENT(IN) ::     t(:)
     1289  CHARACTER(LEN=maxlen), ALLOCATABLE     ::   out(:)
     1290  TYPE(trac_type),            INTENT(IN) ::     t(:)
    12891291  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: tname(:)
    12901292  INTEGER,          OPTIONAL, INTENT(IN) :: igen
     
    13051307INTEGER FUNCTION idxAncestor_1(t, tname, igen) RESULT(out)
    13061308! Return the name of the generation "igen" ancestor of "tname"
    1307   TYPE(tra),         INTENT(IN) :: t(:)
     1309  TYPE(trac_type),   INTENT(IN) :: t(:)
    13081310  CHARACTER(LEN=*),  INTENT(IN) :: tname
    13091311  INTEGER, OPTIONAL, INTENT(IN) :: igen
     
    13121314  out = strIdx(t(:)%name, tname)
    13131315  IF(out == 0)          RETURN
    1314   IF(t(out)%igen <= ig) RETURN
    1315   DO WHILE(t(out)%igen > ig); out = strIdx(t(:)%name, t(out)%prnt); END DO
     1316  IF(t(out)%iGeneration <= ig) RETURN
     1317  DO WHILE(t(out)%iGeneration > ig); out = strIdx(t(:)%name, t(out)%parent); END DO
    13161318END FUNCTION idxAncestor_1
    13171319!------------------------------------------------------------------------------------------------------------------------------
    13181320FUNCTION idxAncestor_m(t, tname, igen) RESULT(out)
    13191321  INTEGER,          ALLOCATABLE          ::   out(:)
    1320   TYPE(tra),                  INTENT(IN) ::     t(:)
     1322  TYPE(trac_type),            INTENT(IN) ::     t(:)
    13211323  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: tname(:)
    13221324  INTEGER,          OPTIONAL, INTENT(IN) :: igen
  • strings_mod.F90

    r1 r2  
    44
    55  PRIVATE
    6   PUBLIC :: modname, init_printout, msg, fmsg, get_in, lunout, prt_level
     6  PUBLIC :: maxlen, init_printout, msg, fmsg, get_in, lunout, prt_level
    77  PUBLIC :: strLower, strHead, strStack,  strClean,  strIdx,  strCount, strReplace
    88  PUBLIC :: strUpper, strTail, strStackm, strReduce, strFind, strParse, cat, find
     
    1313
    1414  INTERFACE get_in;     MODULE PROCEDURE getin_s,  getin_i,  getin_r,  getin_l;  END INTERFACE get_in
    15   INTERFACE  msg;       MODULE PROCEDURE        msg_1,      msg_l1,       msg_m; END INTERFACE  msg
    16   INTERFACE fmsg;       MODULE PROCEDURE       fmsg_1,     fmsg_l1,      fmsg_m; END INTERFACE fmsg
     15  INTERFACE  msg;       MODULE PROCEDURE        msg_1,                    msg_m; END INTERFACE  msg
     16  INTERFACE fmsg;       MODULE PROCEDURE       fmsg_1,                   fmsg_m; END INTERFACE fmsg
    1717  INTERFACE strHead;    MODULE PROCEDURE    strHead_1,                strHead_m; END INTERFACE strHead
    1818  INTERFACE strTail;    MODULE PROCEDURE    strTail_1,                strTail_m; END INTERFACE strTail
     
    3232  INTERFACE testFile;     MODULE PROCEDURE     testFile_1,     testFile_m; END INTERFACE testFile
    3333
    34   CHARACTER(LEN=256), SAVE :: modname = ''                 !--- Current subroutine name
    35   INTEGER,            SAVE :: lunout  = 6                  !--- Printing unit  (default: 6, ie. on screen)
    36   INTEGER,            SAVE :: prt_level = 1                !--- Printing level (default: 1, ie. print all)
    37 
     34  INTEGER, PARAMETER :: maxlen    = 256                    !--- Standard maximum length for strings
     35  INTEGER,      SAVE :: lunout    = 6                      !--- Printing unit  (default: 6, ie. on screen)
     36  INTEGER,      SAVE :: prt_level = 1                      !--- Printing level (default: 1, ie. print all)
    3837
    3938CONTAINS
     
    5756!==============================================================================================================================
    5857SUBROUTINE getin_s(nam, val, def)
    59 USE ioipsl_getin_mod, ONLY: getin
     58USE ioipsl_getincom, ONLY: getin
    6059  CHARACTER(LEN=*), INTENT(IN)    :: nam
    6160  CHARACTER(LEN=*), INTENT(INOUT) :: val
     
    6665!==============================================================================================================================
    6766SUBROUTINE getin_i(nam, val, def)
    68 USE ioipsl_getin_mod, ONLY: getin
     67USE ioipsl_getincom, ONLY: getin
    6968  CHARACTER(LEN=*), INTENT(IN)    :: nam
    7069  INTEGER,          INTENT(INOUT) :: val
     
    7574!==============================================================================================================================
    7675SUBROUTINE getin_r(nam, val, def)
    77 USE ioipsl_getin_mod, ONLY: getin
     76USE ioipsl_getincom, ONLY: getin
    7877  CHARACTER(LEN=*), INTENT(IN)    :: nam
    7978  REAL,             INTENT(INOUT) :: val
     
    8483!==============================================================================================================================
    8584SUBROUTINE getin_l(nam, val, def)
    86 USE ioipsl_getin_mod, ONLY: getin
     85USE ioipsl_getincom, ONLY: getin
    8786  CHARACTER(LEN=*), INTENT(IN)    :: nam
    8887  LOGICAL,          INTENT(INOUT) :: val
     
    9796!=== Display one or several messages, one each line, starting with the current routine name "modname".
    9897!==============================================================================================================================
    99 SUBROUTINE msg_1(str, unit)
    100   CHARACTER(LEN=*),  INTENT(IN) :: str
    101   INTEGER, OPTIONAL, INTENT(IN) :: unit
     98SUBROUTINE msg_1(str, modname, ll, unit)
     99  !--- Display a simple message "str". Optional parameters:
     100  !    * "modname": module name, displayed in front of the message (with ": " separator) if present.
     101  !    * "ll":      message trigger ; message is displayed only if ll==.TRUE.
     102  !    * "unit":    write unit (by default: "lunout")
     103  CHARACTER(LEN=*),           INTENT(IN) :: str
     104  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: modname
     105  LOGICAL,          OPTIONAL, INTENT(IN) :: ll
     106  INTEGER,          OPTIONAL, INTENT(IN) :: unit
    102107  INTEGER :: unt
     108  IF(PRESENT(ll)) THEN; IF(ll) RETURN; END IF
    103109  unt = lunout; IF(PRESENT(unit)) unt = unit
    104   WRITE(unt,'(a)') TRIM(modname)//': '//str
     110  IF(PRESENT(modname)) THEN
     111    WRITE(unt,'(a)') TRIM(modname)//': '//str              !--- Routine name provided
     112  ELSE
     113    WRITE(unt,'(a)') str                                   !--- Simple message
     114  END IF
    105115END SUBROUTINE msg_1
    106116!==============================================================================================================================
    107 SUBROUTINE msg_l1(ll, str, unit)
    108   LOGICAL,           INTENT(IN) :: ll
    109   CHARACTER(LEN=*),  INTENT(IN) :: str
    110   INTEGER, OPTIONAL, INTENT(IN) :: unit
    111   INTEGER :: unt
    112   IF(.NOT.ll) RETURN
    113   unt = lunout; IF(PRESENT(unit)) unt = unit
    114   WRITE(unt,'(a)') TRIM(modname)//': '//str
    115 END SUBROUTINE msg_l1
    116 !==============================================================================================================================
    117 SUBROUTINE msg_m(str, unit, nmax)
    118   CHARACTER(LEN=*),  INTENT(IN) :: str(:)
    119   INTEGER, OPTIONAL, INTENT(IN) :: unit
    120   INTEGER, OPTIONAL, INTENT(IN) :: nmax
    121   CHARACTER(LEN=256), ALLOCATABLE :: s(:)
     117SUBROUTINE msg_m(str, modname, ll, unit, nmax)
     118  !--- Same as msg_1 with multiple strings that are stacked (separator: coma) on up to "nmax" full lines.
     119  CHARACTER(LEN=*),           INTENT(IN) :: str(:)
     120  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: modname
     121  LOGICAL,          OPTIONAL, INTENT(IN) :: ll
     122  INTEGER,          OPTIONAL, INTENT(IN) :: unit
     123  INTEGER,          OPTIONAL, INTENT(IN) :: nmax
     124  CHARACTER(LEN=maxlen), ALLOCATABLE :: s(:)
    122125  INTEGER :: unt, nmx, k
     126  LOGICAL :: lerr
     127  lerr = .TRUE.; IF(PRESENT(ll))  lerr = ll
    123128  unt = lunout ; IF(PRESENT(unit)) unt = unit
    124129  nmx = 128;     IF(PRESENT(nmax)) nmx = nmax
    125130  s = strStackm(str, ', ', nmx)
    126   DO k=1,SIZE(s); WRITE(unt,'(a)') TRIM(modname)//': '//TRIM(s(k)); END DO
     131  IF(PRESENT(modname)) THEN
     132    DO k=1,SIZE(s); CALL msg_1(s(k), modname, lerr, unt); END DO
     133  ELSE
     134    DO k=1,SIZE(s); CALL msg_1(s(k), ll=lerr, unit=unt);  END DO
     135  END IF
    127136END SUBROUTINE msg_m
    128137!==============================================================================================================================
    129 LOGICAL FUNCTION fmsg_1(str, unit) RESULT(lerr)
    130   CHARACTER(LEN=*),  INTENT(IN)  :: str
    131   INTEGER, OPTIONAL, INTENT(IN)  :: unit
     138LOGICAL FUNCTION fmsg_1(str, modname, ll, unit) RESULT(lerr)
     139  CHARACTER(LEN=*),           INTENT(IN) :: str
     140  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: modname
     141  LOGICAL,          OPTIONAL, INTENT(IN) :: ll
     142  INTEGER,          OPTIONAL, INTENT(IN) :: unit
    132143  INTEGER :: unt
    133   lerr = .TRUE.
     144  lerr = .TRUE.; IF(PRESENT(ll))  lerr = ll
    134145  unt = lunout ; IF(PRESENT(unit)) unt = unit
    135   CALL msg_1(str, unt)
     146  IF(PRESENT(modname)) THEN
     147    CALL msg_1(str, modname, lerr, unt)
     148  ELSE
     149    CALL msg_1(str, ll=lerr, unit=unt)
     150  END IF
    136151END FUNCTION fmsg_1
    137152!==============================================================================================================================
    138 LOGICAL FUNCTION fmsg_l1(li, str, unit) RESULT(lerr)
    139   LOGICAL,           INTENT(IN)  :: li
    140   CHARACTER(LEN=*),  INTENT(IN)  :: str
    141   INTEGER, OPTIONAL, INTENT(IN)  :: unit
    142   INTEGER :: unt
    143   lerr = li;     IF(.NOT.lerr) RETURN
    144   unt = lunout ; IF(PRESENT(unit)) unt = unit
    145   CALL msg_l1(lerr, str, unt)
    146 END FUNCTION fmsg_l1
    147 !==============================================================================================================================
    148 LOGICAL FUNCTION fmsg_m(str, unit, nmax) RESULT(lerr)
    149   CHARACTER(LEN=*),  INTENT(IN)  :: str(:)
    150   INTEGER, OPTIONAL, INTENT(IN)  :: unit
    151   INTEGER, OPTIONAL, INTENT(IN)  :: nmax
     153LOGICAL FUNCTION fmsg_m(str, modname, ll, unit, nmax) RESULT(lerr)
     154  CHARACTER(LEN=*),           INTENT(IN)  :: str(:)
     155  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: modname
     156  LOGICAL,          OPTIONAL, INTENT(IN) :: ll
     157  INTEGER,          OPTIONAL, INTENT(IN) :: unit
     158  INTEGER,          OPTIONAL, INTENT(IN)  :: nmax
    152159  INTEGER :: unt, nmx
    153   lerr = .TRUE.
     160  lerr = .TRUE.; IF(PRESENT(ll))  lerr = ll
    154161  unt = lunout ; IF(PRESENT(unit)) unt = unit
    155162  nmx = 128;     IF(PRESENT(nmax)) nmx = nmax
    156   CALL msg_m(str, unt, nmx)
     163  IF(PRESENT(modname)) THEN
     164    CALL msg_m(str, modname, lerr, unt, nmx)
     165  ELSE
     166    CALL msg_m(str, ll=lerr, unit=unt, nmax=nmx)
     167  END IF
    157168END FUNCTION fmsg_m
    158169!==============================================================================================================================
     
    162173!=== Lower/upper case conversion function. ====================================================================================
    163174!==============================================================================================================================
    164 ELEMENTAL CHARACTER(LEN=256) FUNCTION strLower(str) RESULT(out)
     175ELEMENTAL CHARACTER(LEN=maxlen) FUNCTION strLower(str) RESULT(out)
    165176  CHARACTER(LEN=*), INTENT(IN) :: str
    166177  INTEGER :: k
     
    171182END FUNCTION strLower
    172183!==============================================================================================================================
    173 ELEMENTAL CHARACTER(LEN=256) FUNCTION strUpper(str) RESULT(out)
     184ELEMENTAL CHARACTER(LEN=maxlen) FUNCTION strUpper(str) RESULT(out)
    174185  CHARACTER(LEN=*), INTENT(IN) :: str
    175186  INTEGER :: k
     
    188199!===    * strHead(..,.TRUE.)  = 'a_b'         ${str%$sep*}                                                     ================
    189200!==============================================================================================================================
    190 CHARACTER(LEN=256) FUNCTION strHead_1(str,sep,lFirst) RESULT(out)
     201CHARACTER(LEN=maxlen) FUNCTION strHead_1(str,sep,lFirst) RESULT(out)
    191202  CHARACTER(LEN=*),           INTENT(IN) :: str
    192203  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep
     
    203214!==============================================================================================================================
    204215FUNCTION strHead_m(str,sep,lFirst) RESULT(out)
    205   CHARACTER(LEN=256),        ALLOCATABLE :: out(:)
     216  CHARACTER(LEN=maxlen),     ALLOCATABLE :: out(:)
    206217  CHARACTER(LEN=*),           INTENT(IN) :: str(:)
    207218  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep
     
    222233!===    * strHead(..,.TRUE.)  = 'c'           ${str##*$sep}                                                    ================
    223234!==============================================================================================================================
    224 CHARACTER(LEN=256) FUNCTION strTail_1(str,sep,lFirst) RESULT(out)
     235CHARACTER(LEN=maxlen) FUNCTION strTail_1(str,sep,lFirst) RESULT(out)
    225236  CHARACTER(LEN=*),           INTENT(IN) :: str
    226237  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep
     
    237248!==============================================================================================================================
    238249FUNCTION strTail_m(str,sep,lFirst) RESULT(out)
    239   CHARACTER(LEN=256),        ALLOCATABLE :: out(:)
     250  CHARACTER(LEN=maxlen),     ALLOCATABLE :: out(:)
    240251  CHARACTER(LEN=*),           INTENT(IN) :: str(:)
    241252  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep
     
    270281!==============================================================================================================================
    271282FUNCTION strStackm(str, sep, nmax) RESULT(out)
    272   CHARACTER(LEN=256),        ALLOCATABLE :: out(:)
     283  CHARACTER(LEN=maxlen),     ALLOCATABLE :: out(:)
    273284  CHARACTER(LEN=*),           INTENT(IN) :: str(:)
    274285  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep
    275286  INTEGER,          OPTIONAL, INTENT(IN) :: nmax
    276   CHARACTER(LEN=256), ALLOCATABLE :: t(:)
    277   CHARACTER(LEN=256) :: sp
     287  CHARACTER(LEN=maxlen), ALLOCATABLE :: t(:)
     288  CHARACTER(LEN=maxlen) :: sp
    278289  INTEGER :: is, ns, no, mx, n
    279290  IF(SIZE(str) == 0) THEN; out = ['']; RETURN; END IF
     
    328339  CHARACTER(LEN=*), ALLOCATABLE, INTENT(INOUT) :: str1(:)
    329340  INTEGER,          OPTIONAL,    INTENT(OUT)   :: nb
    330   CHARACTER(LEN=256), ALLOCATABLE :: s1(:)
     341  CHARACTER(LEN=maxlen), ALLOCATABLE :: s1(:)
    331342  INTEGER :: k, n, n1
    332343  IF(PRESENT(nb)) nb = 0
     
    342353  CHARACTER(LEN=*),   ALLOCATABLE, INTENT(INOUT) :: str1(:)
    343354  CHARACTER(LEN=*),                INTENT(IN)    :: str2(:)
    344   CHARACTER(LEN=256), ALLOCATABLE :: s1(:), s2(:)
     355  CHARACTER(LEN=maxlen), ALLOCATABLE :: s1(:), s2(:)
    345356  INTEGER :: k
    346357  IF(SIZE(str2)==0) RETURN
     
    432443  LOGICAL, OPTIONAL, INTENT(IN)  :: lSc                              !--- Care about nbs with front sign or in scient. notation
    433444
    434   INTEGER              :: idx0                                       !--- Used to display an identified non-numeric string
    435   INTEGER, ALLOCATABLE :: ii(:)
    436   LOGICAL              :: ll, ls
    437   CHARACTER(LEN=256)  :: d
     445  INTEGER               :: idx0                                      !--- Used to display an identified non-numeric string
     446  INTEGER, ALLOCATABLE  :: ii(:)
     447  LOGICAL               :: ll, ls
     448  CHARACTER(LEN=maxlen) :: d
    438449!  modname = 'strIdx'
    439450  lerr = .FALSE.
     
    545556  DO
    546557    lerr = strIdx_prv(r, delimiter, ib, ie, jd, ll)
    547     IF(fmsg(lerr,'"'//TRIM(r(ib:ie-1))//'" is not numeric')) RETURN
     558    IF(fmsg('"'//TRIM(r(ib:ie-1))//'" is not numeric', ll=lerr)) RETURN
    548559    IF(jd == 0) EXIT
    549560    ib = ie + LEN(delimiter(jd))
     
    560571!==============================================================================================================================
    561572LOGICAL FUNCTION strParse_1(rawList, delimiter, keys, lSc, vals, n) RESULT(lerr)
    562   CHARACTER(LEN=*),                          INTENT(IN)  :: rawList, delimiter
    563   CHARACTER(LEN=256), ALLOCATABLE,           INTENT(OUT) :: keys(:)
    564   LOGICAL,                         OPTIONAL, INTENT(IN)  :: lSc      !--- Take care about numbers in scientific notation
    565   CHARACTER(LEN=256), ALLOCATABLE, OPTIONAL, INTENT(OUT) :: vals(:)
    566   INTEGER,                         OPTIONAL, INTENT(OUT) :: n
     573  CHARACTER(LEN=*),                             INTENT(IN)  :: rawList, delimiter
     574  CHARACTER(LEN=maxlen), ALLOCATABLE,           INTENT(OUT) :: keys(:)
     575  LOGICAL,                            OPTIONAL, INTENT(IN)  :: lSc      !--- Take care about numbers in scientific notation
     576  CHARACTER(LEN=maxlen), ALLOCATABLE, OPTIONAL, INTENT(OUT) :: vals(:)
     577  INTEGER,                            OPTIONAL, INTENT(OUT) :: n
    567578  LOGICAL :: ll
    568579!  modname = 'strParse'
     
    574585!==============================================================================================================================
    575586LOGICAL FUNCTION strParse_m(rawList, delimiter, keys, lSc, vals, n, id) RESULT(lerr)
    576   CHARACTER(LEN=*),                          INTENT(IN)  :: rawList, delimiter(:)
    577   CHARACTER(LEN=256),           ALLOCATABLE, INTENT(OUT) :: keys(:)  !--- Parsed keys vector
    578   LOGICAL,            OPTIONAL,              INTENT(IN)  :: lSc      !--- Take care about numbers in scientific notation
    579   CHARACTER(LEN=256), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: vals(:)  !--- Values for <name>=<value> keys
    580   INTEGER,            OPTIONAL,              INTENT(OUT) :: n        !--- Length of the parsed vector
    581   INTEGER,            OPTIONAL, ALLOCATABLE, INTENT(OUT) :: id(:)    !--- Indexes of the separators in "delimiter(:)" vector
     587  CHARACTER(LEN=*),                             INTENT(IN)  :: rawList, delimiter(:)
     588  CHARACTER(LEN=maxlen),           ALLOCATABLE, INTENT(OUT) :: keys(:)  !--- Parsed keys vector
     589  LOGICAL,               OPTIONAL,              INTENT(IN)  :: lSc      !--- Take care about numbers in scientific notation
     590  CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: vals(:)  !--- Values for <name>=<value> keys
     591  INTEGER,               OPTIONAL,              INTENT(OUT) :: n        !--- Length of the parsed vector
     592  INTEGER,               OPTIONAL, ALLOCATABLE, INTENT(OUT) :: id(:)    !--- Indexes of the separators in "delimiter(:)" vector
    582593
    583594  CHARACTER(LEN=1024) :: r
     
    587598!  modname = 'strParse'
    588599  ll = .FALSE.; IF(PRESENT(lSc)) ll = lSc
    589   IF(test(fmsg(strCount_1m(rawList, delimiter, nk, ll), "Couldn't parse list: non-numerical strings were found"),lerr)) RETURN
     600  IF(test(fmsg("Couldn't parse list: non-numerical strings were found", ll=strCount_1m(rawList, delimiter, nk, ll)),lerr)) RETURN
    590601
    591602  !--- FEW ALLOCATIONS
     
    600611  ib = 1
    601612  DO ik = 1, nk-1
    602     IF(test(fmsg(strIdx_prv(r, delimiter, ib, ie, jd, ll),'Non-numeric values found'),lerr)) RETURN
     613    IF(test(fmsg('Non-numeric values found', ll=strIdx_prv(r, delimiter, ib, ie, jd, ll)),lerr)) RETURN
    603614    keys(ik) = r(ib:ie-1)
    604615    IF(PRESENT(vals)) CALL parseKeys(keys(ik), vals(ik))             !--- Parse a <key>=<val> pair
     
    674685  CHARACTER(LEN=*),           TARGET, INTENT(IN) :: s0
    675686  CHARACTER(LEN=*), OPTIONAL, TARGET, INTENT(IN) :: s1, s2, s3, s4, s5, s6, s7, s8, s9
    676   CHARACTER(LEN=256), ALLOCATABLE :: out(:)
    677   CHARACTER(LEN=256), POINTER     :: s
     687  CHARACTER(LEN=maxlen), ALLOCATABLE :: out(:)
     688  CHARACTER(LEN=maxlen), POINTER     :: s
    678689  LOGICAL :: lv(10)
    679690  INTEGER :: iv
     
    693704  CHARACTER(LEN=*),           TARGET, DIMENSION(:), INTENT(IN) :: s0
    694705  CHARACTER(LEN=*), OPTIONAL, TARGET, DIMENSION(:), INTENT(IN) :: s1, s2, s3, s4, s5, s6, s7, s8, s9
    695   CHARACTER(LEN=256), ALLOCATABLE :: out(:,:)
    696   CHARACTER(LEN=256), POINTER     :: s(:)
     706  CHARACTER(LEN=maxlen), ALLOCATABLE :: out(:,:)
     707  CHARACTER(LEN=maxlen), POINTER     :: s(:)
    697708  LOGICAL :: lv(10)
    698709  INTEGER :: nrow, ncol, iv, n
     
    707718    END SELECT
    708719    n = SIZE(s, DIM=1)
    709     IF(n/=nrow) THEN; CALL msg('Can''t concatenate vectors of differing lengths',1); STOP; END IF
     720    IF(n/=nrow) THEN; CALL msg("Can't concatenate vectors of differing lengths"); STOP; END IF
    710721    out(:,iv) = s(:)
    711722  END DO
     
    748759    END SELECT
    749760    n = SIZE(i, DIM=1)
    750     IF(n/=nrow) THEN; CALL msg('Can''t concatenate vectors of differing lengths',1); STOP; END IF
     761    IF(n/=nrow) THEN; CALL msg("Can't concatenate vectors of differing lengths"); STOP; END IF
    751762    out(:,iv) = i(:)
    752763  END DO
     
    789800    END SELECT
    790801    n = SIZE(r, DIM=1)
    791     IF(n/=nrow) THEN; CALL msg('Can''t concatenate vectors of differing lengths',1); STOP; END IF
     802    IF(n/=nrow) THEN; CALL msg("Can't concatenate vectors of differing lengths"); STOP; END IF
    792803    out(:,iv) = r(:)
    793804  END DO
     
    830841    END SELECT
    831842    n = SIZE(d, DIM=1)
    832     IF(n/=nrow) THEN; CALL msg('Can''t concatenate vectors of differing lengths',1); STOP; END IF
     843    IF(n/=nrow) THEN; CALL msg("Can't concatenate vectors of differing lengths"); STOP; END IF
    833844    out(:,iv) = d(:)
    834845  END DO
     
    852863
    853864  CHARACTER(LEN=2048) :: row
    854   CHARACTER(LEN=256)  :: rFm, el
    855   CHARACTER(LEN=256), ALLOCATABLE :: d(:,:)
     865  CHARACTER(LEN=maxlen)  :: rFm, el
     866  CHARACTER(LEN=maxlen), ALLOCATABLE :: d(:,:)
    856867  CHARACTER(LEN=1) :: s1, sp
    857868  INTEGER :: is, ii, ir, np, nrow, unt, ic
     
    870881
    871882  !--- CHECK ARGUMENTS COHERENCE
    872   lerr = np /= SIZE(titles); IF(fmsg(lerr, 'string "pattern" length and titles list mismatch')) RETURN
     883  lerr = np /= SIZE(titles); IF(fmsg('string "pattern" length and titles list mismatch', ll=lerr)) RETURN
    873884  IF(ls) THEN; ns = SIZE(s, DIM=1); ncol = ncol + SIZE(s, DIM=2)
    874885    lerr = COUNT([(p(ic:ic)=='s', ic=1, np)]) /= SIZE(s, DIM=2)
     
    880891    lerr = COUNT([(p(ic:ic)=='r', ic=1, np)]) /= SIZE(r, DIM=2)
    881892  END IF
    882 
    883   IF(fmsg(lerr, 'string "pattern" length and arguments number mismatch')) RETURN
    884   lerr = ncol /= SIZE(titles); IF(fmsg(lerr, '"titles" length and arguments number mismatch')) RETURN
    885   lerr = ls.AND.li.AND.ns/=ni; IF(fmsg(lerr, 'string and integer arguments lengths mismatch')) RETURN
    886   lerr = ls.AND.lr.AND.ns/=nr; IF(fmsg(lerr,    'string and real arguments lengths mismatch')) RETURN
    887   lerr = li.AND.lr.AND.ni/=nr; IF(fmsg(lerr,   'integer and real arguments lengths mismatch')) RETURN
     893  IF(fmsg('string "pattern" length and arguments number mismatch', ll=lerr)) RETURN
     894  lerr = ncol /= SIZE(titles); IF(fmsg('"titles" length and arguments number mismatch', ll=lerr)) RETURN
     895  lerr = ls.AND.li.AND.ns/=ni; IF(fmsg('string and integer arguments lengths mismatch', ll=lerr)) RETURN
     896  lerr = ls.AND.lr.AND.ns/=nr; IF(fmsg(   'string and real arguments lengths mismatch', ll=lerr)) RETURN
     897  lerr = li.AND.lr.AND.ni/=nr; IF(fmsg(  'integer and real arguments lengths mismatch', ll=lerr)) RETURN
    888898  nrow = MAX(ns,ni,nr)+1
    889899  nmx = nrow; IF(PRESENT(nmax)) nmx = MIN(nmx,nmax+1)
     
    912922    END DO
    913923    nr = LEN_TRIM(row)-1                                             !--- Final separator removed
    914     CALL msg(row(1:nr), unt)
     924    CALL msg(row(1:nr), unit=unt)
    915925    IF(ir /= 1) CYCLE                                                !--- Titles are underlined
    916926    row=''; DO ic=1,ncol; row=TRIM(row)//REPEAT('-',n(ic))//'+'; END DO
    917     CALL msg(row(1:LEN_TRIM(row)-1), unt)
     927    CALL msg(row(1:LEN_TRIM(row)-1), unit=unt)
    918928  END DO
    919929
     
    932942  LOGICAL,          OPTIONAL, INTENT(IN)  :: llast         !--- Last variable: no final ','
    933943
    934   CHARACTER(LEN=256)  :: rFm, el
    935   CHARACTER(LEN=256), ALLOCATABLE :: d(:,:)
    936   CHARACTER(LEN=:),   ALLOCATABLE :: sp, row
     944  CHARACTER(LEN=maxlen)  :: rFm, el
     945  CHARACTER(LEN=maxlen), ALLOCATABLE :: d(:,:)
     946  CHARACTER(LEN=:),      ALLOCATABLE :: sp, row
    937947  INTEGER :: is, ii, ir, nrow, ic
    938948  INTEGER :: ns, ni, nr, ncol, np
     
    957967    lerr = COUNT([(p(ic:ic)=='r', ic=1, np)]) /= SIZE(r, DIM=2)
    958968  END IF
    959   IF(fmsg(lerr, 'string "pattern" length and arguments number mismatch')) RETURN
    960   lerr = ncol /= SIZE(titles); IF(fmsg(lerr, '"titles" length and arguments number mismatch')) RETURN
    961   lerr = ls.AND.li.AND.ns/=ni; IF(fmsg(lerr, 'string and integer arguments lengths mismatch')) RETURN
    962   lerr = ls.AND.lr.AND.ns/=nr; IF(fmsg(lerr,    'string and real arguments lengths mismatch')) RETURN
    963   lerr = li.AND.lr.AND.ni/=nr; IF(fmsg(lerr,   'integer and real arguments lengths mismatch')) RETURN
     969  IF(fmsg('string "pattern" length and arguments number mismatch', ll=lerr)) RETURN
     970  lerr = ncol /= SIZE(titles); IF(fmsg('"titles" length and arguments number mismatch', ll=lerr)) RETURN
     971  lerr = ls.AND.li.AND.ns/=ni; IF(fmsg('string and integer arguments lengths mismatch', ll=lerr)) RETURN
     972  lerr = ls.AND.lr.AND.ns/=nr; IF(fmsg(   'string and real arguments lengths mismatch', ll=lerr)) RETURN
     973  lerr = li.AND.lr.AND.ni/=nr; IF(fmsg(  'integer and real arguments lengths mismatch', ll=lerr)) RETURN
    964974
    965975  !--- Allocate the assembled quantities array
     
    10121022  CHARACTER(LEN=*), OPTIONAL, INTENT(IN)  :: err_msg, nam(:), subn   !--- Error message, variables and calling subroutine names
    10131023  INTEGER,          OPTIONAL, INTENT(IN)  :: nmax, unit              !--- Maximum number of lines to display (default: all)
    1014   CHARACTER(LEN=256),         ALLOCATABLE :: ttl(:)
     1024  CHARACTER(LEN=maxlen),      ALLOCATABLE :: ttl(:)
    10151025  LOGICAL,                    ALLOCATABLE :: m(:)
    10161026  INTEGER,                    ALLOCATABLE :: ki(:), kj(:)
    10171027  INTEGER                                 :: i, j, k, rk, rk1, ib, ie, itr, nm, unt, nmx, nv
    1018   CHARACTER(LEN=256)                      :: mes, sub, fm='(f12.9)', v, s
    1019   CHARACTER(LEN=256),         ALLOCATABLE :: vnm(:)
     1028  CHARACTER(LEN=maxlen)                   :: mes, sub, fm='(f12.9)', v, s
     1029  CHARACTER(LEN=maxlen),      ALLOCATABLE :: vnm(:)
    10201030
    10211031  lerr = ANY(ll); IF(.NOT.lerr) RETURN                               !--- No outliers -> finished
     
    10281038
    10291039  rk = SIZE(n); nv = SIZE(vnm)
    1030   IF(test(fmsg(nv /= 1 .AND. nv /= n(rk), 'In "'//TRIM(sub)//'": SIZE(nam) /= 1 or =last "n" element'    , unt),lerr)) RETURN
    1031   IF(test(fmsg(SIZE(a) /= SIZE(ll),       'In "'//TRIM(sub)//'": "ll" and "a" sizes mismatch'            , unt),lerr)) RETURN
    1032   IF(test(fmsg(SIZE(a) /= PRODUCT(n),     'In "'//TRIM(sub)//'": profile "n" does not match "a" and "ll"', unt),lerr)) RETURN
    1033 
    1034   WRITE(unt,*)'Outliers detected by '//TRIM(sub)//': '//TRIM(mes)
     1040  IF(test(fmsg('SIZE(nam) /= 1 and /= last "n" element', sub, nv /= 1 .AND. nv /= n(rk), unt),lerr)) RETURN
     1041  IF(test(fmsg('ll" and "a" sizes mismatch',             sub, SIZE(a) /= SIZE(ll),       unt),lerr)) RETURN
     1042  IF(test(fmsg('profile "n" does not match "a" and "ll', sub, SIZE(a) /= PRODUCT(n),     unt),lerr)) RETURN
     1043  CALL msg(mes, sub, unit=unt)
    10351044
    10361045  !--- SCALAR CASE: single value to display
     
    10511060    IF(nv == 1) lerr = dispTable('sr', ttl,               s=cat(PACK(nam,ll)), r=cat(PACK(a,ll)), rFmt=fm, nmax=nmax)
    10521061    IF(nv /= 1) lerr = dispTable('ir', ['name ','value'], i=cat(PACK(ki,m)),   r=cat(PACK(a,ll)), rFmt=fm, nmax=nmax)
    1053     CALL msg(lerr,'In '//TRIM(sub)//": can't display outliers table", unt)
     1062    CALL msg("can't display outliers table", sub, lerr, unt)
    10541063    RETURN
    10551064  END IF
     
    10681077    IF(rk==2) lerr = dispTable('ir',  ttl, i=cat(PACK(ki,m)),            r=cat(PACK(a(ib:ie),m)), rFmt=fm, nmax=nmax)
    10691078    IF(rk==3) lerr = dispTable('iir', ttl, i=cat(PACK(ki,m),PACK(kj,m)), r=cat(PACK(a(ib:ie),m)), rFmt=fm, nmax=nmax)
    1070     CALL msg(lerr,'In '//TRIM(sub)//": can't display outliers table", unt)
    1071     IF(lerr) THEN; CALL msg("Can't display outliers table"); RETURN; END IF
     1079    CALL msg("can't display outliers table", sub, lerr, unt)
     1080    IF(lerr) RETURN
    10721081  END DO
    10731082END FUNCTION dispOutliers_1
     
    10821091  INTEGER,          OPTIONAL, INTENT(IN)  :: nmax, unit              !--- Maximum number of lines to display (default: all)
    10831092
    1084   CHARACTER(LEN=256)                      :: mes, sub, fm='(f12.9)', prf
    1085   CHARACTER(LEN=256),         ALLOCATABLE :: ttl(:), vnm(:)
     1093  CHARACTER(LEN=maxlen)                   :: mes, sub, fm='(f12.9)', prf
     1094  CHARACTER(LEN=maxlen),      ALLOCATABLE :: ttl(:), vnm(:)
    10861095  LOGICAL,                    ALLOCATABLE :: m(:)
    10871096  INTEGER,                    ALLOCATABLE :: ki(:), kj(:), kl(:)
     
    10961105  nmx = SIZE(a);                  IF(PRESENT(nmax))    nmx = MIN(nmx,nmax)!--- Maximum number of lines to print
    10971106  unt = lunout;                   IF(PRESENT(unit))    unt = unit         !--- Unit to print messages
    1098   lerr = SIZE(vnm) /= nv;         IF(fmsg(lerr, 'In "dispOutlayers_2": SIZE(nam) /= SIZE(a,2)'  ,unt)) RETURN
    1099   lerr = SIZE(a,1) /= SIZE(ll);   IF(fmsg(lerr,'In '//TRIM(sub)//': "ll" and "a" sizes mismatch',unt)) RETURN
    1100   lerr = SIZE(a,1) /= PRODUCT(n); IF(fmsg(lerr,'In '//TRIM(sub)//': profile "n" does not match "a" and "ll"',unt)) RETURN
     1107  lerr = SIZE(vnm) /= nv;         IF(fmsg('SIZE(nam) /= SIZE(a,2)',                  sub, lerr, unt)) RETURN
     1108  lerr = SIZE(a,1) /= SIZE(ll);   IF(fmsg('"ll" and "a" sizes mismatch',             sub, lerr, unt)) RETURN
     1109  lerr = SIZE(a,1) /= PRODUCT(n); IF(fmsg('profile "n" does not match "a" and "ll"', sub, lerr, unt)) RETURN
    11011110
    11021111  SELECT CASE(rk1)                                                   !--- Indices list
     
    11161125  IF(rk == 3) lerr = dispTable(prf, ttl, i = cat(PACK(ki,ll),PACK(kj,ll),PACK(kl,ll)), &
    11171126                     r = val, rFmt=fm, nmax=nmax)
    1118   CALL msg(lerr,'In '//TRIM(sub)//": can't display outliers table", unt)
     1127  CALL msg("can't display outliers table", sub, lerr, unt)
    11191128END FUNCTION dispOutliers_2
    11201129!==============================================================================================================================
     
    11251134!==============================================================================================================================
    11261135LOGICAL FUNCTION reduceExpr_1(str, val) RESULT(lerr)
    1127   CHARACTER(LEN=*),    INTENT(IN)  :: str
    1128   CHARACTER(LEN=256), INTENT(OUT) :: val
    1129 
    1130   CHARACTER(LEN=256)               :: v
    1131   CHARACTER(LEN=1024)              :: s, vv
     1136  CHARACTER(LEN=*),      INTENT(IN)  :: str
     1137  CHARACTER(LEN=maxlen), INTENT(OUT) :: val
     1138
     1139  CHARACTER(LEN=maxlen)              :: v
     1140  CHARACTER(LEN=1024)                :: s, vv
    11321141  CHARACTER(LEN=1024), ALLOCATABLE :: vl(:)
    11331142  INTEGER,             ALLOCATABLE :: ip(:)
     
    11411150  ll = strCount(s,')',nn)
    11421151  lerr = nl /= nn
    1143   IF(fmsg(lerr, 'Mismatching number of opening and closing parenthesis: '//TRIM(s))) RETURN
     1152  IF(fmsg('Mismatching number of opening and closing parenthesis: '//TRIM(s), ll=lerr)) RETURN
    11441153  nl = 2*nl-1
    11451154
     
    11751184!==============================================================================================================================
    11761185LOGICAL FUNCTION reduceExpr_basic(str, val) RESULT(lerr)
    1177   CHARACTER(LEN=*),   INTENT(IN)  :: str
    1178   CHARACTER(LEN=*),   INTENT(OUT) :: val
    1179   DOUBLE PRECISION,   ALLOCATABLE :: vl(:)
    1180   INTEGER,            ALLOCATABLE :: id(:)
    1181   CHARACTER(LEN=256), ALLOCATABLE :: ky(:)
    1182   CHARACTER(LEN=1),   ALLOCATABLE :: op(:)
     1186  CHARACTER(LEN=*),      INTENT(IN)  :: str
     1187  CHARACTER(LEN=*),      INTENT(OUT) :: val
     1188  DOUBLE PRECISION,      ALLOCATABLE :: vl(:)
     1189  INTEGER,               ALLOCATABLE :: id(:)
     1190  CHARACTER(LEN=maxlen), ALLOCATABLE :: ky(:)
     1191  CHARACTER(LEN=1),      ALLOCATABLE :: op(:)
    11831192
    11841193  CHARACTER(LEN=1024) :: s
     
    11941203  vl = str2dble(ky)                                                            !--- Conversion to doubles
    11951204  lerr = ANY(vl >= HUGE(1.d0))
    1196   IF(fmsg(lerr,'Some values are non-numeric in: '//TRIM(s))) RETURN            !--- Non-numerical values found
     1205  IF(fmsg('Some values are non-numeric in: '//TRIM(s), ll=lerr)) RETURN        !--- Non-numerical values found
    11971206  DO io = 1, SIZE(op)                                                          !--- Loop on known operators (order matters !)
    11981207    DO i = SIZE(id), 1, -1                                                     !--- Loop on found operators
     
    12181227!==============================================================================================================================
    12191228FUNCTION reduceExpr_m(str, val) RESULT(lerr)
    1220   LOGICAL,            ALLOCATABLE              :: lerr(:)
    1221   CHARACTER(LEN=*),                INTENT(IN)  :: str(:)
    1222   CHARACTER(LEN=256), ALLOCATABLE, INTENT(OUT) :: val(:)
     1229  LOGICAL,               ALLOCATABLE              :: lerr(:)
     1230  CHARACTER(LEN=*),                   INTENT(IN)  :: str(:)
     1231  CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) :: val(:)
    12231232  INTEGER :: i
    12241233  ALLOCATE(lerr(SIZE(str)),val(SIZE(str)))
     
    12771286END FUNCTION str2dble
    12781287!==============================================================================================================================
    1279 ELEMENTAL CHARACTER(LEN=256) FUNCTION bool2str(b) RESULT(out)
     1288ELEMENTAL CHARACTER(LEN=maxlen) FUNCTION bool2str(b) RESULT(out)
    12801289  LOGICAL, INTENT(IN) :: b
    12811290  WRITE(out,*)b
     
    12831292END FUNCTION bool2str
    12841293!==============================================================================================================================
    1285 ELEMENTAL CHARACTER(LEN=256) FUNCTION int2str(i, nDigits) RESULT(out)
     1294ELEMENTAL CHARACTER(LEN=maxlen) FUNCTION int2str(i, nDigits) RESULT(out)
    12861295  INTEGER,           INTENT(IN) :: i
    12871296  INTEGER, OPTIONAL, INTENT(IN) :: nDigits
     
    12921301END FUNCTION int2str
    12931302!==============================================================================================================================
    1294 ELEMENTAL CHARACTER(LEN=256) FUNCTION real2str(r,fmt) RESULT(out)
     1303ELEMENTAL CHARACTER(LEN=maxlen) FUNCTION real2str(r,fmt) RESULT(out)
    12951304  REAL,                       INTENT(IN) :: r
    12961305  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: fmt
     
    13001309END FUNCTION real2str
    13011310!==============================================================================================================================
    1302 ELEMENTAL CHARACTER(LEN=256) FUNCTION dble2str(d,fmt) RESULT(out)
     1311ELEMENTAL CHARACTER(LEN=maxlen) FUNCTION dble2str(d,fmt) RESULT(out)
    13031312  DOUBLE PRECISION,           INTENT(IN) :: d
    13041313  CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: fmt
     
    13671376  CHARACTER(LEN=*),   INTENT(IN)  :: message, items, reason
    13681377  INTEGER,  OPTIONAL, INTENT(IN)  :: nmax
    1369   CHARACTER(LEN=256), ALLOCATABLE :: s(:)
     1378  CHARACTER(LEN=maxlen), ALLOCATABLE :: s(:)
    13701379  INTEGER :: i, nmx
    13711380  nmx = 256; IF(PRESENT(nmax)) nmx=nmax
  • trac_types_mod.F90

    r1 r2  
    11MODULE trac_types_mod
    22
     3  USE strings_mod, ONLY: maxlen
     4  PRIVATE
     5
    36!=== TRACERS DESCRIPTOR DERIVED TYPE AND ASSOCIATED ROUTINES INTERFACES =======================================================
    4   PRIVATE
    5   PUBLIC :: tra, iso, kys
     7  PUBLIC :: trac_type, isot_type, keys_type
    68!------------------------------------------------------------------------------------------------------------------------------
    7   TYPE kys                                                           !=== TYPE FOR A SET OF KEYS ASSOCIATED TO AN ELEMENT
    8     CHARACTER(LEN=256)              :: name                          !--- Tracer name
    9     CHARACTER(LEN=256), ALLOCATABLE :: key(:)                        !--- Keys string list
    10     CHARACTER(LEN=256), ALLOCATABLE :: val(:)                        !--- Corresponding values string list
    11   END TYPE kys
     9  TYPE :: keys_type                                        !=== TYPE FOR A SET OF KEYS ASSOCIATED TO AN ELEMENT
     10    CHARACTER(LEN=maxlen)              :: name             !--- Tracer name
     11    CHARACTER(LEN=maxlen), ALLOCATABLE :: key(:)           !--- Keys string list
     12    CHARACTER(LEN=maxlen), ALLOCATABLE :: val(:)           !--- Corresponding values string list
     13  END TYPE keys_type
    1214!------------------------------------------------------------------------------------------------------------------------------
    13   TYPE tra                                                           !=== TYPE FOR SINGLE TRACER
    14     CHARACTER(LEN=256)   :: name = ''                                !--- Name
    15     CHARACTER(LEN=256)   :: nam1 = ''                                !--- Generation 1 ancestor name
    16     CHARACTER(LEN=256)   :: prnt = ''                                !--- Parent name
    17     CHARACTER(LEN=256)   :: lnam = ''                                !--- Long name (with adv. scheme)
    18     CHARACTER(LEN=256)   :: type = 'tracer'                          !--- Type (so far: 'tracer'/'tag')
    19     CHARACTER(LEN=256)   :: phas = 'g'                               !--- Phase ('g'as/'l'iquid/'s'olid)
    20     CHARACTER(LEN=256)   :: comp                                     !--- Coma-separated list of components (Ex: lmdz,inca)
    21     INTEGER              :: iadv = 10                                !--- Advection scheme used
    22     INTEGER              :: igen = 1                                 !--- Generation number (>=1)
    23     INTEGER              :: itr  = 0                                 !--- Index in tr_seri (0: not in physics)
    24     INTEGER              :: iprnt = 0                                !--- Parent index
    25     INTEGER, ALLOCATABLE :: idesc(:)                                 !--- Descendants index (in growing generation order)
    26     INTEGER              :: ndesc = 0                                !--- Number of descendants (all generations)
    27     INTEGER              :: nchld = 0                                !--- Number of childs    (first generation)
    28     INTEGER              :: iso_igr = 0                              !--- Isotopes group index in isotopes(:)
    29     INTEGER              :: iso_num = 0                              !--- Isotope  name  index in isotopes(iso_igr)%trac(:)
    30     INTEGER              :: iso_zon = 0                              !--- Isotope  zone  index in isotopes(iso_igr)%zone(:)
    31     INTEGER              :: iso_pha = 0                              !--- Isotope  phase index in isotopes(iso_igr)%phas
    32     TYPE(kys)            :: keys                                     !--- <key>=<val> pairs vector
    33   END TYPE tra
     15  TYPE :: trac_type                                        !=== TYPE FOR A SINGLE TRACER NAMED "name"
     16    CHARACTER(LEN=maxlen) :: name        = ''              !--- Name of the tracer
     17    CHARACTER(LEN=maxlen) :: gen0Name    = ''              !--- First generation ancestor name
     18    CHARACTER(LEN=maxlen) :: parent      = ''              !--- Parent name
     19    CHARACTER(LEN=maxlen) :: longName    = ''              !--- Long name (with advection scheme suffix)
     20    CHARACTER(LEN=maxlen) :: type        = 'tracer'        !--- Type  (so far: 'tracer' / 'tag')
     21    CHARACTER(LEN=maxlen) :: phase       = 'g'             !--- Phase ('g'as / 'l'iquid / 's'olid)
     22    CHARACTER(LEN=maxlen) :: component                     !--- Coma-separated list of components (Ex: lmdz,inca)
     23    INTEGER               :: iadv        = 10              !--- Advection scheme used
     24    INTEGER               :: iGeneration = 1               !--- Generation number (>=1)
     25    LOGICAL               :: isAdvected  = .FALSE.         !--- "true" tracers: iadv > 0 . COUNT(     isAdvected) =nqtrue
     26    LOGICAL               :: isH2Ofamily = .FALSE.         !--- H2O tracers/isotopes/tags. COUNT(.NOT.isH2Ofamily)=nqtottr
     27    INTEGER               :: iqParent    = 0               !--- Parent index
     28    INTEGER,  ALLOCATABLE :: iqDescen(:)                   !--- Descendants index (in growing generation order)
     29    INTEGER               :: nqDescen    = 0               !--- Number of descendants (all generations)
     30    INTEGER               :: nqChilds    = 0               !--- Number of childs    (first generation)
     31    INTEGER               :: iso_iGroup  = 0               !--- Isotopes group index in isotopes(:)
     32    INTEGER               :: iso_iName   = 0               !--- Isotope  name  index in isotopes(iso_iGroup)%trac(:)
     33    INTEGER               :: iso_iZone   = 0               !--- Isotope  zone  index in isotopes(iso_iGroup)%zone(:)
     34    INTEGER               :: iso_iPhase  = 0               !--- Isotope  phase index in isotopes(iso_iGroup)%phas
     35    TYPE(keys_type)       :: keys                          !--- <key>=<val> pairs vector
     36  END TYPE trac_type
    3437!------------------------------------------------------------------------------------------------------------------------------
    35   TYPE iso                                                           !=== TYPE FOR ISOTOPES FAMILY DESCENDING ON TRACER "prnt"
    36     CHARACTER(LEN=256)              :: prnt                          !--- Isotopes family name (parent tracer name ; ex: H2O)
    37     LOGICAL                         :: check=.FALSE.                 !--- Triggering of the checking routines
    38     TYPE(kys),          ALLOCATABLE :: keys(:)                       !--- Isotopes keys/values pairs list (length: niso)
    39     CHARACTER(LEN=256), ALLOCATABLE :: trac(:)                       !--- Isotopes + tagging tracers list (length: nitr)
    40     CHARACTER(LEN=256), ALLOCATABLE :: zone(:)                       !--- Geographic tagging zones names list
    41     CHARACTER(LEN=256)              :: phas = 'g'                    !--- Phases list: [g][l][s]
    42     INTEGER                         :: niso=0, nzon=0, nitr=0, npha=0!--- Number of isotopes, zones, total isotopes and phases
    43     INTEGER,            ALLOCATABLE :: iTraPha(:,:)   ! (iqiso)      !--- Idx in "trac(1:niso)" = f(name(1:nitr)),phas)
    44     INTEGER,            ALLOCATABLE :: iZonIso(:,:)   ! (index_trac) !--- Idx in "trac(1:nitr)" = f(zone, name(1:niso))
    45   END TYPE iso
     38  TYPE :: isot_type                                        !=== TYPE FOR AN ISOTOPES FAMILY DESCENDING ON TRACER "parent"
     39    CHARACTER(LEN=maxlen)              :: parent           !--- Isotopes family name (parent tracer name ; ex: H2O)
     40    LOGICAL                            :: check=.FALSE.    !--- Triggering of the checking routines
     41    TYPE(keys_type),       ALLOCATABLE :: keys(:)          !--- Isotopes keys/values pairs list     (length: niso)
     42    CHARACTER(LEN=maxlen), ALLOCATABLE :: trac(:)          !--- Isotopes + tagging tracers list     (length: nitr)
     43    CHARACTER(LEN=maxlen), ALLOCATABLE :: zone(:)          !--- Geographic tagging zones names list (length: nzon)
     44    CHARACTER(LEN=maxlen)              :: phase = 'g'      !--- Phases list: [g][l][s]              (length: npha)
     45    INTEGER                            :: niso = 0         !--- Number of isotopes, excluding tagging tracers
     46    INTEGER                            :: nzon = 0         !--- Number of geographic tagging zones
     47    INTEGER                            :: nitr = 0         !--- Number of isotopes, including tagging tracers
     48    INTEGER                            :: npha = 0         !--- Number phases
     49    INTEGER,               ALLOCATABLE :: iTraPha(:,:)     !--- Idx in "trac(1:niso)" = f(name(1:nitr)),phas)
     50                                                           !---        "iTraPha" former name: "iqiso"
     51    INTEGER,               ALLOCATABLE :: iZonIso(:,:)     !--- Idx in "trac(1:nitr)" = f(zone, name(1:niso))
     52                                                           !---        "iZonIso" former name: "index_trac"
     53  END TYPE isot_type
    4654
    4755END MODULE trac_types_mod
Note: See TracChangeset for help on using the changeset viewer.