Changeset 5183 for LMDZ6/trunk/libf
- Timestamp:
- Sep 10, 2024, 5:14:23 PM (3 months ago)
- Location:
- LMDZ6/trunk/libf
- Files:
-
- 1 added
- 21 edited
Legend:
- Unmodified
- Added
- Removed
-
LMDZ6/trunk/libf/dyn3d/check_isotopes.F90
r4984 r5183 2 2 USE strings_mod, ONLY: maxlen, msg, strIdx, strStack, int2str, real2str 3 3 USE infotrac, ONLY: nqtot, niso, nphas, isotope, isoCheck, iqIsoPha, isoSelect, & 4 ntiso, iH2O, nzone, tracers, isoName, itZonIso, getKey 4 ntiso, iH2O, nzone, tracers, isoName, itZonIso 5 USE iso_params_mod, ONLY: tnat_H216O, tnat_H217O, tnat_H218O, tnat_HDO, tnat_HTO 6 USE ioipsl_getincom, ONLY: getin 5 7 IMPLICIT NONE 6 8 include "dimensions.h" … … 20 22 deltaDmin =-999.0, & 21 23 ridicule = 1e-12 22 INTEGER, SAVE :: iso_eau, iso_HDO, iso_O18, & 23 iso_O17, iso_HTO 24 LOGICAL, SAVE :: first=.TRUE. 25 LOGICAL, PARAMETER :: tnat1=.TRUE. 24 INTEGER, SAVE :: iso_eau, iso_O17, iso_O18, iso_HDO, iso_HTO 25 LOGICAL, SAVE :: ltnat1, first=.TRUE. 26 26 27 27 modname='check_isotopes' … … 30 30 IF(niso == 0) RETURN !--- No isotopes => finished 31 31 IF(first) THEN 32 iso_eau = strIdx(isoName,'H216O') 33 iso_HDO = strIdx(isoName,'HDO') 34 iso_O18 = strIdx(isoName,'H218O') 35 iso_O17 = strIdx(isoName,'H217O') 36 iso_HTO = strIdx(isoName,'HTO') 37 if (tnat1) then 38 tnat(:)=1.0 39 else 40 IF(getKey('tnat', tnat)) CALL abort_gcm(modname, 'missing isotopic parameter', 1) 41 endif 32 ltnat1 = .TRUE.; CALL getin('tnateq1', ltnat1) 33 ALLOCATE(tnat(niso)) 34 iso_eau = strIdx(isoName,'H216O'); IF(iso_eau /= 0) tnat(iso_eau) = tnat_H216O 35 iso_O17 = strIdx(isoName,'H217O'); IF(iso_O17 /= 0) tnat(iso_O17) = tnat_H217O 36 iso_O18 = strIdx(isoName,'H218O'); IF(iso_O18 /= 0) tnat(iso_O18) = tnat_H218O 37 iso_HDO = strIdx(isoName,'HDO'); IF(iso_HDO /= 0) tnat(iso_HDO) = tnat_HDO 38 iso_HTO = strIdx(isoName,'HTO'); IF(iso_HTO /= 0) tnat(iso_HTO) = tnat_HTO 39 IF(ltnat1) tnat(:) = 1. 42 40 first = .FALSE. 43 41 END IF -
LMDZ6/trunk/libf/dyn3d/dynetat0.F90
r5084 r5183 6 6 ! Purpose: Initial state reading. 7 7 !------------------------------------------------------------------------------- 8 USE infotrac, ONLY: nqtot, tracers, niso, iqIsoPha, iH2O, isoName 8 USE infotrac, ONLY: nqtot, tracers, niso, iqIsoPha, iH2O, isoName, & 9 new2oldH2O, newHNO3, oldHNO3 9 10 USE strings_mod, ONLY: maxlen, msg, strStack, real2str, int2str 10 11 USE netcdf, ONLY: NF90_OPEN, NF90_NOWRITE, NF90_INQ_VARID, & 11 12 NF90_CLOSE, NF90_GET_VAR, NF90_NoErr 12 USE readTracFiles_mod, ONLY: new2oldH2O, newHNO3, oldHNO3, getKey13 13 USE control_mod, ONLY: planet_type 14 14 USE assert_eq_m, ONLY: assert_eq … … 19 19 USE temps_mod, ONLY: annee_ref, day_ini, day_ref, itau_dyn, start_time 20 20 USE ener_mod, ONLY: etot0,ptot0,ztot0,stot0,ang0 21 #ifdef CPP_IOIPSL 22 USE IOIPSL, ONLY: getin 23 #else 24 USE ioipsl_getincom, ONLY: getin 25 #endif 26 USE iso_params_mod ! tnat_* and alpha_ideal_* 21 27 22 28 IMPLICIT NONE … … 42 48 INTEGER :: iq, fID, vID, idecal, iqParent, iName, iZone, iPhase 43 49 REAL :: time, tnat, alpha_ideal, tab_cntrl(length) !--- RUN PARAMS TABLE 44 LOGICAL :: lSkip, ll 45 LOGICAL,PARAMETER :: tnat1=.TRUE. 50 LOGICAL :: lSkip, ll, ltnat1 46 51 !------------------------------------------------------------------------------- 47 52 modname="dynetat0" … … 116 121 var="temps" 117 122 IF(NF90_INQ_VARID(fID,var,vID)/=NF90_NoErr) THEN 118 CALL msg(' missing field <temps> ; trying with <Time>', modname)123 CALL msg('Missing field <temps> ; trying with <Time>', modname) 119 124 var="Time" 120 125 CALL err(NF90_INQ_VARID(fID,var,vID),"inq",var) … … 133 138 ll = NF90_INQ_VARID(fID, 'HNO3tot', vID) /= NF90_NoErr !--- DETECT OLD REPRO start.nc FILE 134 139 #endif 140 ltnat1 = .TRUE.; CALL getin('tnateq1', ltnat1) 135 141 DO iq=1,nqtot 136 142 var = tracers(iq)%name … … 148 154 !-------------------------------------------------------------------------------------------------------------------------- 149 155 ELSE IF(NF90_INQ_VARID(fID, oldVar, vID) == NF90_NoErr) THEN !=== TRY WITH ALTERNATE NAME 150 CALL msg(' Tracer <'//TRIM(var)//'> is missing=> initialized to <'//TRIM(oldVar)//'>', modname)156 CALL msg('Missing tracer <'//TRIM(var)//'> => initialized to <'//TRIM(oldVar)//'>', modname) 151 157 CALL err(NF90_GET_VAR(fID,vID,q(:,:,:,iq)),"get",oldVar) 152 158 !-------------------------------------------------------------------------------------------------------------------------- … … 156 162 iqParent = tracers(iq)%iqParent 157 163 IF(tracers(iq)%iso_iZone == 0) THEN 158 if (tnat1) then 159 tnat=1.0 160 alpha_ideal=1.0 161 write(*,*) 'attention dans dynetat0: les alpha_ideal sont a 1' 162 else 163 IF(getKey('tnat', tnat, isoName(iName)) .OR. getKey('alpha', alpha_ideal, isoName(iName))) & 164 CALL abort_gcm(TRIM(modname), 'missing isotopic parameters', 1) 165 endif 166 CALL msg('Tracer <'//TRIM(var)//'> is missing => initialized with a simplified Rayleigh distillation law.', modname) 164 IF(ltnat1) THEN 165 tnat = 1.0 166 alpha_ideal = 1.0 167 CALL msg(' !!! Beware: alpha_ideal put to 1 !!!', modname) 168 ELSE 169 SELECT CASE(isoName(iName)) 170 CASE('H216O'); tnat = tnat_H216O; alpha_ideal = alpha_ideal_H216O 171 CASE('H217O'); tnat = tnat_H217O; alpha_ideal = alpha_ideal_H217O 172 CASE('H218O'); tnat = tnat_H218O; alpha_ideal = alpha_ideal_H218O 173 CASE('HDO'); tnat = tnat_HDO; alpha_ideal = alpha_ideal_HDO 174 CASE('HTO'); tnat = tnat_HTO; alpha_ideal = alpha_ideal_HTO 175 CASE DEFAULT; CALL abort_gcm(TRIM(modname),'unknown isotope "'//TRIM(isoName(iName))//'" ; check tracer.def file',1) 176 END SELECT 177 END IF 178 CALL msg('Missing tracer <'//TRIM(var)//'> => initialized with a simplified Rayleigh distillation law.', modname) 167 179 q(:,:,:,iq) = q(:,:,:,iqParent)*tnat*(q(:,:,:,iqParent)/30.e-3)**(alpha_ideal-1.) 168 180 ELSE 169 CALL msg(' Tracer <'//TRIM(var)//'> is missing=> initialized to its parent isotope concentration.', modname)181 CALL msg('Missing tracer <'//TRIM(var)//'> => initialized to its parent isotope concentration.', modname) 170 182 ! Camille 9 mars 2023: attention!! seuls les tags qui correspondent à 171 183 ! izone=izone_init (définie dans isotrac_mod) sont initialisés comme … … 181 193 !-------------------------------------------------------------------------------------------------------------------------- 182 194 ELSE !=== MISSING: SET TO 0 183 CALL msg(' Tracer <'//TRIM(var)//'> is missing=> initialized to zero', modname)195 CALL msg('Missing tracer <'//TRIM(var)//'> => initialized to zero', modname) 184 196 q(:,:,:,iq)=0. 185 197 !-------------------------------------------------------------------------------------------------------------------------- -
LMDZ6/trunk/libf/dyn3d/iniacademic.F90
r5084 r5183 5 5 6 6 USE filtreg_mod, ONLY: inifilr 7 USE infotrac, ONLY: nqtot, niso, iqIsoPha, tracers, getKey, isoName 7 USE infotrac, ONLY: nqtot, niso, iqIsoPha, tracers, getKey, isoName, addPhase 8 8 USE control_mod, ONLY: day_step,planet_type 9 9 use exner_hyb_m, only: exner_hyb … … 21 21 USE temps_mod, ONLY: annee_ref, day_ini, day_ref 22 22 USE ener_mod, ONLY: etot0,ptot0,ztot0,stot0,ang0 23 USE readTracFiles_mod, ONLY: addPhase24 23 use netcdf, only : NF90_NOWRITE,NF90_OPEN,NF90_NOERR,NF90_INQ_VARID 25 24 use netcdf, only : NF90_CLOSE, NF90_GET_VAR 25 USE iso_params_mod ! tnat_* and alpha_ideal_* 26 26 27 27 … … 80 80 81 81 REAL zdtvr, tnat, alpha_ideal 82 LOGICAL ,PARAMETER :: tnat1=.true.82 LOGICAL :: ltnat1 83 83 84 84 character(len=*),parameter :: modname="iniacademic" … … 309 309 ! bulk initialization of tracers 310 310 if (planet_type=="earth") then 311 ltnat1 = .TRUE.; CALL getin('tnateq1', ltnat1) 311 312 ! Earth: first two tracers will be water 312 313 do iq=1,nqtot … … 322 323 iqParent = tracers(iq)%iqParent 323 324 IF(tracers(iq)%iso_iZone == 0) THEN 324 if (tnat1) then 325 tnat=1.0 326 alpha_ideal=1.0 327 write(*,*) 'Attention dans iniacademic: alpha_ideal=1' 328 else 329 IF(getKey('tnat', tnat, isoName(iName)) .OR. getKey('alpha', alpha_ideal, isoName(iName))) & 330 CALL abort_gcm(TRIM(modname), 'missing isotopic parameters', 1) 331 endif 325 IF(ltnat1) THEN 326 tnat = 1.0 327 alpha_ideal = 1.0 328 WRITE(lunout, *)'In '//TRIM(modname)//': !!! Beware: alpha_ideal put to 1 !!!' 329 ELSE 330 SELECT CASE(isoName(iName)) 331 CASE('H216O'); tnat = tnat_H216O; alpha_ideal = alpha_ideal_H216O 332 CASE('H217O'); tnat = tnat_H217O; alpha_ideal = alpha_ideal_H217O 333 CASE('H218O'); tnat = tnat_H218O; alpha_ideal = alpha_ideal_H218O 334 CASE('HDO'); tnat = tnat_HDO; alpha_ideal = alpha_ideal_HDO 335 CASE('HTO'); tnat = tnat_HTO; alpha_ideal = alpha_ideal_HTO 336 CASE DEFAULT 337 CALL abort_gcm(TRIM(modname),'unknown isotope "'//TRIM(isoName(iName))//'" ; check tracer.def file',1) 338 END SELECT 339 END IF 332 340 q(:,:,iq) = q(:,:,iqParent)*tnat*(q(:,:,iqParent)/30.e-3)**(alpha_ideal-1.) 333 341 ELSE !IF(tracers(iq)%iso_iZone == 0) THEN -
LMDZ6/trunk/libf/dyn3d/qminimum.F
r5001 r5183 4 4 SUBROUTINE qminimum( q,nqtot,deltap ) 5 5 6 USE infotrac, ONLY: niso, ntiso, iqIsoPha, tracers6 USE infotrac, ONLY: niso, ntiso, iqIsoPha, tracers, addPhase 7 7 USE strings_mod, ONLY: strIdx 8 USE readTracFiles_mod, ONLY: addPhase9 8 IMPLICIT none 10 9 c -
LMDZ6/trunk/libf/dyn3d_common/infotrac.F90
r5003 r5183 3 3 MODULE infotrac 4 4 5 USE strings_mod, ONLY: msg, fmsg, maxlen, cat, dispTable, int2str, bool2str, strStack, strParse 6 USE readTracFiles_mod, ONLY: trac_type, readTracersFiles, tracers, setGeneration, itZonIso, nzone, tran0, isoZone, & 7 delPhase, niso, getKey, isot_type, processIsotopes, isotope, maxTableWidth, iqIsoPha, nphas, ixIso, isoPhas, & 8 addPhase, iH2O, addKey, isoSelect, testTracersFiles, isoKeys, indexUpdate, iqWIsoPha, nbIso, ntiso, isoName, isoCheck 5 USE strings_mod, ONLY: msg, maxlen, cat, dispTable, int2str, bool2str, strStack, strParse, strCount, strIdx 6 USE readTracFiles_mod, ONLY: readTracersFiles, maxTableWidth, tisot=>isot_type, addPhase, addKey, iH2O, & 7 indexUpdate, keys_type, testTracersFiles, processIsotopes, trac=>tracers, delPhase, getKey, tran0 8 USE readTracFiles_mod, ONLY: new2oldH2O, newHNO3, oldHNO3 9 9 10 IMPLICIT NONE 10 11 … … 16 17 PUBLIC :: nqtot, nbtr, nqo, nqCO2, nqtottr !--- Main dimensions 17 18 PUBLIC :: conv_flg, pbl_flg !--- Convection & boundary layer activation keys 19 PUBLIC :: new2oldH2O, newHNO3, oldHNO3 !--- For backwards compatibility in dynetat0 20 PUBLIC :: addPhase, delPhase !--- Add/remove the phase from the name of a tracer 18 21 19 22 !=== FOR ISOTOPES: General 20 23 PUBLIC :: isot_type, nbIso !--- Derived type, full isotopes families database + nb of families 21 PUBLIC :: isoSelect, ixIso !--- Isotopes family selection tool + selected family index24 PUBLIC :: isoSelect, ixIso, isoFamilies !--- Isotopes families selection tool + selected index + list 22 25 !=== FOR ISOTOPES: Specific to water 23 PUBLIC :: iH2O !--- H2O isotopes class index26 PUBLIC :: iH2O !--- Value of "ixIso" for "H2O" isotopes class 24 27 PUBLIC :: min_qParent, min_qMass, min_ratio !--- Min. values for various isotopic quantities 25 28 !=== FOR ISOTOPES: Depending on the selected isotopes family 26 PUBLIC :: isotope , isoKeys !--- Selected isotopes database + associated keys (cf.getKey)27 PUBLIC :: iso Name, isoZone, isoPhas !--- Isotopes andtagging zones names, phases28 PUBLIC :: niso, nzone, nphas, ntiso !--- " " numbers + isotopes & tagging tracers number29 PUBLIC :: itZonIso !--- i dx "it" (in "isoName(1:niso)") = function(tagging idx, isotope idx)30 PUBLIC :: iqIsoPha !--- i dx "iq" (in "qx") = function(isotope idx, phase idx) + aliases29 PUBLIC :: isotope !--- Selected isotopes database (argument of getKey) 30 PUBLIC :: isoKeys, isoName, isoZone, isoPhas !--- Isotopes keys & names, tagging zones names, phases 31 PUBLIC :: niso, ntiso, nzone, nphas !--- Number of " " 32 PUBLIC :: itZonIso !--- index "it" in "isoName(1:niso)" = f(tagging idx, isotope idx) 33 PUBLIC :: iqIsoPha !--- index "iq" in "qx" = f(isotope idx, phase idx) 31 34 PUBLIC :: isoCheck !--- Run isotopes checking routines 32 35 !=== FOR BOTH TRACERS AND ISOTOPES … … 36 39 ! |--------------------+-----------------------+-----------------+---------------+----------------------------| 37 40 ! | water in different | water tagging | water isotopes | other tracers | additional tracers moments | 38 ! | phases: H2O_[gls ]| isotopes | | | for higher order schemes |41 ! | phases: H2O_[glsrb]| isotopes | | | for higher order schemes | 39 42 ! |--------------------+-----------------------+-----------------+---------------+----------------------------| 40 43 ! | | | | | | … … 50 53 ! |-----------------------------------------------------------------------------------------------------------| 51 54 ! NOTES FOR THIS TABLE: 52 ! * Used "niso", "nzone" and "ntiso" are components of "isotopes(ip)" for water (isotopes(ip)% parent== 'H2O'),55 ! * Used "niso", "nzone" and "ntiso" are components of "isotopes(ip)" for water (isotopes(ip)%name == 'H2O'), 53 56 ! since water is so far the sole tracers family, except passive CO2, removed from the main tracers table. 54 57 ! * For water, "nqo" is equal to the more general field "isotopes(ip)%nphas". 55 58 ! * "niso", "nzone", "ntiso", "nphas" are defined for other isotopic tracers families, if any. 56 ! 57 !=== DERIVED TYPE EMBEDDING MOST OF THE TRACERS-RELATED QUANTITIES (LENGTH: nqtot) 59 ! * If you deal with an isotopes family other than "H2O" ("Sulf" in the example), a good practice is to keep 60 ! track of the isotopes class (of its index) before switching to it at the beginning of the dedicated code: 61 ! - first time (use selection by name and compute the corresponding index iSulf) : 62 ! i0=ixIso; IF(.NOT.isoSelect('Sulf')) CALL abort_gcm("Can't select isotopes class", modname, 1); iS=ixIso 63 ! - next times (use selection by index - "iS" has been computed at first call): 64 ! i0=ixIso; IF(.NOT.isoSelect(iS)) CALL abort_gcm("Can't select isotopes class", modname, 1) 65 ! and to switch back to the original category when you're done with "Sulf": 66 ! IF(.NOT.isoSelect(i0)) CALL abort_gcm("Can't select isotopes class", modname, 1) 67 ! to restore the original isotopes category (before dealing with "Sulf" (most of the time "H2O"). 68 ! 69 !=== LOCAL DERIVED TYPE "trac_type" EMBEDDING MOST OF THE TRACERS-RELATED QUANTITIES (LENGTH: nqtot) 58 70 ! Each entry is accessible using "%" sign. 59 71 ! |-------------+------------------------------------------------------+-------------+------------------------+ … … 61 73 ! |-------------+------------------------------------------------------+-------------+------------------------+ 62 74 ! | name | Name (short) | tname | | 75 ! | keys | key/val pairs accessible with "getKey" routine | / | | 63 76 ! | gen0Name | Name of the 1st generation ancestor | / | | 64 77 ! | parent | Name of the parent | / | | 65 78 ! | longName | Long name (with adv. scheme suffix) for outputs | ttext | | 66 79 ! | type | Type (so far: tracer or tag) | / | tracer,tag | 67 ! | phase | Phases list ("g"as / "l"iquid / "s"olid) | / | [g][l][s] | 80 ! | phase | Phases list ("g"as / "l"iquid / "s"olid | | [g|l|s|r|b] | 81 ! | | "r"(cloud) / "b"lowing) | / | | 68 82 ! | component | Name(s) of the merged/cumulated section(s) | / | coma-separated names | 69 83 ! | iGeneration | Generation (>=1) | / | | … … 72 86 ! | nqDescen | Number of the descendants (all generations) | nqdesc | 1:nqtot | 73 87 ! | nqChildren | Number of childs (1st generation only) | nqfils | 1:nqtot | 74 ! | keys | key/val pairs accessible with "getKey" routine | / | |75 88 ! | iadv | Advection scheme number | iadv | 1,2,10-20(exc.15,19),30| 76 ! | isAdvected | advected tracers flag (.TRUE. if iadv >= 0) | / | nqtrue .TRUE. values |77 ! | isInPhysics | tracers not extracted from the main table in physics | / | nqtottr .TRUE. values |78 89 ! | iso_iGroup | Isotopes group index in isotopes(:) | / | 1:nbIso | 79 90 ! | iso_iName | Isotope name index in isotopes(iso_iGroup)%trac(:) | iso_indnum | 1:niso | … … 87 98 ! | entry | length | Meaning | Former name | Possible values | 88 99 ! |-----------------+--------------------------------------------------+--------------------+-----------------+ 89 ! | parent | Parent tracer (isotopes family name)| | |100 ! | name | Name of the isotopes class (family) | | | 90 101 ! | keys | niso | Isotopes keys/values pairs list + number | | | 91 102 ! | trac | ntiso | Isotopes + tagging tracers list + number | / | ntraciso | | 92 103 ! | zone | nzone | Geographic tagging zones list + number | / | ntraceurs_zone | | 93 ! | phase | nphas | Phases list + number | | [g ][l][s], 1:3|104 ! | phase | nphas | Phases list + number | | [g|l|s|r|b] 1:5 | 94 105 ! | iqIsoPha | Index in "qx" = f(name(1:ntiso)),phas) | iqiso | 1:nqtot | 95 106 ! | itZonIso | Index in "trac(1:ntiso)"= f(zone, name(1:niso)) | index_trac | 1:ntiso | 96 107 ! +-----------------+--------------------------------------------------+--------------------+-----------------+ 97 108 109 !------------------------------------------------------------------------------------------------------------------------------ 110 TYPE :: trac_type !=== TYPE FOR A SINGLE TRACER NAMED "name" 111 CHARACTER(LEN=maxlen) :: name = '' !--- Name of the tracer 112 TYPE(keys_type) :: keys !--- <key>=<val> pairs vector (general container) 113 CHARACTER(LEN=maxlen) :: gen0Name = '' !--- First generation ancestor name 114 CHARACTER(LEN=maxlen) :: parent = '' !--- Parent name 115 CHARACTER(LEN=maxlen) :: longName = '' !--- Long name (with advection scheme suffix) 116 CHARACTER(LEN=maxlen) :: type = 'tracer' !--- Type (so far: 'tracer' / 'tag') 117 CHARACTER(LEN=maxlen) :: phase = 'g' !--- Phase ('g'as / 'l'iquid / 's'olid) 118 CHARACTER(LEN=maxlen) :: component = '' !--- Coma-separated list of components (Ex: lmdz,inca) 119 INTEGER :: iGeneration = -1 !--- Generation number (>=0) 120 INTEGER :: iqParent = 0 !--- Parent index 121 INTEGER, ALLOCATABLE :: iqDescen(:) !--- Descendants index (in growing generation order) 122 INTEGER :: nqDescen = 0 !--- Number of descendants (all generations) 123 INTEGER :: nqChildren = 0 !--- Number of children (first generation) 124 INTEGER :: iadv = 10 !--- Advection scheme used 125 INTEGER :: iso_iGroup = 0 !--- Isotopes group index in isotopes(:) 126 INTEGER :: iso_iName = 0 !--- Isotope name index in isotopes(iso_iGroup)%trac(:) 127 INTEGER :: iso_iZone = 0 !--- Isotope zone index in isotopes(iso_iGroup)%zone(:) 128 INTEGER :: iso_iPhase = 0 !--- Isotope phase index in isotopes(iso_iGroup)%phase 129 END TYPE trac_type 130 !------------------------------------------------------------------------------------------------------------------------------ 131 TYPE :: isot_type !=== TYPE FOR THE ISOTOPES FAMILY DESCENDING ON TRACER "name" 132 CHARACTER(LEN=maxlen) :: name !--- Isotopes family name (ex: H2O) 133 TYPE(keys_type), ALLOCATABLE :: keys(:) !--- Isotopes keys/values pairs list (length: niso) 134 LOGICAL :: check=.FALSE. !--- Flag for checking routines triggering 135 CHARACTER(LEN=maxlen), ALLOCATABLE :: trac(:) !--- Isotopes + tagging tracers list (length: ntiso) 136 CHARACTER(LEN=maxlen), ALLOCATABLE :: zone(:) !--- Geographic tagging zones names list (length: nzone) 137 CHARACTER(LEN=maxlen) :: phase = 'g' !--- Phases list: [g|l|s|r|b] (length: nphas) 138 INTEGER :: niso = 0 !--- Number of isotopes, excluding tagging tracers 139 INTEGER :: ntiso = 0 !--- Number of isotopes, including tagging tracers 140 INTEGER :: nzone = 0 !--- Number of geographic tagging zones 141 INTEGER :: nphas = 0 !--- Number of phases 142 INTEGER, ALLOCATABLE :: iqIsoPha(:,:) !--- Idx in "tracers(1:nqtot)" = f( name(1:ntiso) ,phas) 143 INTEGER, ALLOCATABLE :: itZonIso(:,:) !--- Idx in "trac(1:ntiso)" = f(zone,name(1:niso)) 144 END TYPE isot_type 145 !------------------------------------------------------------------------------------------------------------------------------ 146 INTERFACE isoSelect; MODULE PROCEDURE isoSelectByIndex, isoSelectByName; END INTERFACE isoSelect 147 !------------------------------------------------------------------------------------------------------------------------------ 148 149 !=== THRESHOLDS FOR WATER 98 150 REAL, PARAMETER :: min_qParent = 1.e-30, min_qMass = 1.e-18, min_ratio = 1.e-16 ! MVals et CRisi 99 151 100 152 !=== DIMENSIONS OF THE TRACERS TABLES AND OTHER SCALAR VARIABLES 101 INTEGER, SAVE :: nqtot, &!--- Tracers nb in dynamics (incl. higher moments + H2O)102 nbtr, &!--- Tracers nb in physics (excl. higher moments + H2O)103 nqo, &!--- Number of water phases153 INTEGER, SAVE :: nqtot, & !--- Tracers nb in dynamics (incl. higher moments + H2O) 154 nbtr, & !--- Tracers nb in physics (excl. higher moments + H2O) 155 nqo, & !--- Number of water phases 104 156 nqtottr, & !--- Number of tracers passed to phytrac (TO BE DELETED ?) 105 157 nqCO2 !--- Number of tracers of CO2 (ThL) 106 CHARACTER(LEN=maxlen), SAVE :: type_trac !--- Keyword for tracers type 158 CHARACTER(LEN=maxlen), SAVE :: type_trac !--- Keyword for tracers type(s) 159 160 !=== NUMBER AND LIST OF DEFINED ISOTOPES FAMILIES 161 INTEGER, SAVE :: nbIso !--- Number of defined isotopes classes 162 CHARACTER(LEN=maxlen), SAVE, ALLOCATABLE :: isoFamilies(:) !--- Generation 0 tracer name for each isotopes family (nbIso) 163 164 !=== QUANTITIES RELATED TO THE CURRENTLY SELECTED ISOTOPES CLASS (USUALLY H2O) 165 TYPE(isot_type), SAVE, POINTER :: isotope !--- Selected isotopes database (=isotopes(ixIso)) 166 TYPE(keys_type), SAVE, POINTER :: isoKeys(:) !--- Database to get isotopes keys using "getKey" (niso) 167 CHARACTER(LEN=maxlen), SAVE, POINTER :: isoName(:), & !--- Isotopes list including tagging tracers, no phase (ntiso) 168 isoZone(:), & !--- Geographic tagging zones list (nzone) 169 isoPhas !--- Used phases names ([g|l|s|r|b]) (nphas) 170 INTEGER, SAVE, POINTER :: itZonIso(:,:), & !--- Idx "it" in isoName(1:niso) = f(tagging idx, isotope idx) 171 iqIsoPha(:,:) !--- Idx "iq" in qx = f(isotope idx, phase idx) 172 INTEGER, SAVE :: ixIso, & !--- Idx in "isoFamilies" of currently selectd class 173 niso, & !--- Number of isotopes 174 ntiso, & !--- Number of isotopes + tagging tracers 175 nzone, & !--- Number of tagging zones 176 nphas !--- Number of phases 177 LOGICAL, SAVE :: isoCheck !--- Isotopes checking routines triggering flag 107 178 108 179 !=== VARIABLES FOR INCA 109 INTEGER, SAVE, ALLOCATABLE :: conv_flg(:), & !--- Convection activation ; needed for INCA (nbtr) 110 pbl_flg(:) !--- Boundary layer activation ; needed for INCA (nbtr) 180 INTEGER, DIMENSION(:), SAVE, ALLOCATABLE :: & 181 conv_flg, pbl_flg !--- Convection / boundary layer activation (nbtr) 182 183 !=== TRACERS/ISOTOPES DESCRIPTORS: EFFECTIVE STORAGE (LOCAL DERIVED TYPES) 184 TYPE(trac_type), SAVE, ALLOCATABLE, TARGET :: tracers(:) 185 TYPE(isot_type), SAVE, ALLOCATABLE, TARGET :: isotopes(:) 111 186 112 187 CONTAINS … … 114 189 SUBROUTINE init_infotrac 115 190 USE control_mod, ONLY: planet_type 191 #ifdef CPP_IOIPSL 192 USE IOIPSL, ONLY: getin 193 #else 194 USE ioipsl_getincom, only: getin 195 #endif 196 #ifdef CPP_PARA 197 USE parallel_lmdz, ONLY: is_master 198 #endif 116 199 #ifdef REPROBUS 117 USE CHEM_REP, 200 USE CHEM_REP, ONLY: Init_chem_rep_trac 118 201 #endif 119 202 IMPLICIT NONE … … 142 225 !------------------------------------------------------------------------------------------------------------------------------ 143 226 ! Local variables 144 INTEGER, ALLOCATABLE :: hadv(:), vadv(:) 227 INTEGER, ALLOCATABLE :: hadv(:), vadv(:), itmp(:) !--- Horizontal/vertical transport scheme number 145 228 #ifdef INCA 146 229 INTEGER, ALLOCATABLE :: had (:), hadv_inca(:), conv_flg_inca(:), &!--- Variables specific to INCA … … 149 232 INTEGER :: nqINCA 150 233 #endif 234 #ifndef CPP_PARA 235 LOGICAL :: is_master=.TRUE. 236 #endif 151 237 CHARACTER(LEN=2) :: suff(9) !--- Suffixes for schemes of order 3 or 4 (Prather) 152 238 CHARACTER(LEN=3) :: descrq(30) !--- Advection scheme description tags 153 CHARACTER(LEN=maxlen) :: msg1, texp, ttp 239 CHARACTER(LEN=maxlen) :: msg1, texp, ttp, ky, nam, val !--- Strings for messages and expanded tracers type 154 240 INTEGER :: fType !--- Tracers description file type ; 0: none 155 241 !--- 1/2/3: "traceur.def"/"tracer.def"/"tracer_*.def" 156 242 INTEGER :: nqtrue !--- Tracers nb from tracer.def (no higher order moments) 157 243 INTEGER :: iad !--- Advection scheme number 158 INTEGER :: iq, jq, nt, im, nm !--- Indexes and temporary variables 159 LOGICAL :: lerr, ll 244 INTEGER :: iq, jq, it, nt, im, nm, ig !--- Indexes and temporary variables 245 LOGICAL :: lerr, lInit 246 TYPE(keys_type), ALLOCATABLE, TARGET :: tra(:) !--- Tracers descriptor as in readTracFiles_mod 247 TYPE(tisot), ALLOCATABLE :: iso(:) !--- Isotopes descriptor as in readTracFiles_mod 160 248 TYPE(trac_type), ALLOCATABLE, TARGET :: ttr(:) 161 TYPE(trac_type), POINTER :: t 1, t(:)162 CHARACTER(LEN=maxlen), ALLOCATABLE :: types_trac(:) !--- Keyword for tracers type(s), parsed version163 249 TYPE(trac_type), POINTER :: t(:), t1 250 TYPE(keys_type), POINTER :: k(:) 251 CHARACTER(LEN=maxlen), ALLOCATABLE :: types_trac(:) !--- Keywords for tracers type(s), parsed version 164 252 CHARACTER(LEN=*), PARAMETER :: modname="init_infotrac" 165 253 !------------------------------------------------------------------------------------------------------------------------------ … … 171 259 descrq(10:20) = ['VL1','VLP','FH1','FH2','VLH',' ','PPM','PPS','PPP',' ','SLP'] 172 260 descrq(30) = 'PRA' 173 174 CALL msg('type_trac = "'//TRIM(type_trac)//'"', modname) 175 176 lerr=strParse(type_trac, '|', types_trac, n=nt) 177 IF (nt .GT. 1) THEN 178 IF (nt .GT. 2) CALL abort_gcm(modname, 'you need to modify type_trac, this version is not supported by lmdz', 1) 179 if (nt .EQ. 2) type_trac=types_trac(2) 180 ENDIF 181 182 183 261 262 CALL msg('type_trac = "'//TRIM(type_trac)//'"', modname, is_master) 263 IF(strCount(type_trac, '|', nt)) CALL abort_gcm(modname, 'Could''nt parse the "type_trac" string with delimiter "|"', 1) 264 IF(nt >= 3) CALL abort_gcm(modname, 'you need to modify type_trac, this version is not supported by lmdz', 1) 265 IF(strParse(type_trac, '|', types_trac, n=nt)) CALL abort_gcm(modname, "couldn't parse "//'"type_trac"', 1) 266 IF(nt == 2) type_trac = types_trac(2) ! TO BE DELETED SOON 267 268 lInit = .NOT.ALLOCATED(trac) 269 270 !############################################################################################################################## 271 IF(lInit .AND. is_master) THEN !=== SKIPED IF ALREADY DONE 272 !############################################################################################################################## 184 273 !--- MESSAGE ABOUT THE CHOSEN CONFIGURATION 185 274 msg1 = 'For type_trac = "'//TRIM(type_trac)//'":' … … 209 298 #endif 210 299 END SELECT 211 212 nqCO2 = COUNT( [type_trac == 'inco', type_trac == 'co2i'] ) 213 214 !============================================================================================================================== 215 ! 1) Get the numbers of: true (first order only) tracers "nqtrue", water tracers "nqo" (vapor/liquid/solid) 216 !============================================================================================================================== 217 texp = type_trac !=== EXPANDED VERSION OF "type_trac", WITH "|" SEPARATOR 300 !############################################################################################################################## 301 END IF 302 !############################################################################################################################## 303 304 !============================================================================================================================== 305 ! 0) DETERMINE THE TYPE OF THE INPUT TRACERS DESCRIPTION FILE AND READ IT ; TRANSFER THE NEEDED QUANTITIES TO LOCAL "tracers". 306 !============================================================================================================================== 307 texp = type_trac !=== EXPANDED (WITH "|" SEPARATOR) "type_trac" 218 308 IF(texp == 'inco') texp = 'co2i|inca' 219 309 IF(texp /= 'lmdz') texp = 'lmdz|'//TRIM(texp) 220 221 !=== DETERMINE THE TYPE OF THE INPUT TRACERS DESCRIPTION FILE 222 IF(testTracersFiles(modname, texp, fType, .TRUE.)) CALL abort_gcm(modname, 'problem with tracers file(s)',1) 310 IF(testTracersFiles(modname, texp, fType, lInit.AND.is_master)) CALL abort_gcm(modname, 'problem with tracers file(s)',1) 223 311 ttp = type_trac; IF(fType /= 1) ttp = texp 224 225 IF(readTracersFiles(ttp, lRepr=type_trac=='repr')) CALL abort_gcm(modname, 'problem with tracers file(s)',1)226 312 !--------------------------------------------------------------------------------------------------------------------------- 227 IF(fType == 0) CALL abort_gcm(modname, 'Missing tracers file: "traceur.def", "tracer.def" or "tracer_<keyword>.deffile.',1)313 IF(fType == 0) CALL abort_gcm(modname, 'Missing "traceur.def", "tracer.def" or "tracer_<keyword>.def tracers file.',1) 228 314 !--------------------------------------------------------------------------------------------------------------------------- 229 IF(fType == 1 .AND. ANY(['inca','inco']==type_trac)) THEN !=== FOUND OLD STYLE INCA "traceur.def" 315 IF(fType == 1 .AND. ANY(['inca', 'inco'] == type_trac) .AND. lInit) & !=== FOUND OLD STYLE INCA "traceur.def" 316 CALL abort_gcm(modname, 'retro-compatibility with old-style INCA traceur.def files has been disabled.', 1) 230 317 !--------------------------------------------------------------------------------------------------------------------------- 318 319 !############################################################################################################################## 320 IF(lInit) THEN 321 IF(readTracersFiles(ttp, tra, type_trac == 'repr')) CALL abort_gcm(modname, 'problem with tracers file(s)',1) 322 ELSE 323 tra = trac 324 END IF 325 CALL msg('No tracers description file(s) reading needed: already done', modname, .NOT.lInit.AND.is_master) 326 !############################################################################################################################## 327 328 !--- POPULATE SOME EXPLICIT (ACCESSIBLE THROUGH "%") KEYS OF THE LOCAL TRACERS DESCRIPTION DERIVED TYPE 329 ! To be defined: iqParent, iq/nqDescen, nqChildren (in indexUpdate), longName, iso_i*, iadv (later) 330 ALLOCATE(tracers(SIZE(tra))) 331 DO iq = 1, SIZE(tra); t1 => tracers(iq) 332 t1%keys = tra(iq) 333 msg1 = '" for tracer nr. '//TRIM(int2str(iq)) 334 ky='name '; IF(getKey(ky, t1%name, iq, tra)) CALL abort_gcm(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1) 335 msg1 = '" for "'//TRIM(t1%name)//'"' 336 ky='gen0Name '; IF(getKey(ky, t1%gen0Name, iq, tra)) CALL abort_gcm(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1) 337 ky='parent '; IF(getKey(ky, t1%parent, iq, tra)) CALL abort_gcm(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1) 338 ky='type '; IF(getKey(ky, t1%type, iq, tra)) CALL abort_gcm(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1) 339 ky='phase '; IF(getKey(ky, t1%phase, iq, tra)) CALL abort_gcm(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1) 340 ky='component '; IF(getKey(ky, t1%component, iq, tra)) CALL abort_gcm(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1) 341 ky='iGeneration'; IF(getKey(ky, t1%iGeneration, iq, tra)) CALL abort_gcm(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1) 342 END DO 343 344 !============================================================================================================================== 345 ! 1) Get various numbers: "nqtrue" (first order only tracers), "nqo" (water phases), 'nbtr' (tracers passed to physics), etc. 346 !============================================================================================================================== 347 nqtrue = SIZE(tracers) !--- "true" tracers 348 nqo = COUNT(tracers(:)%component == 'lmdz' .AND. delPhase(tracers(:)%name) == 'H2O') !--- Water phases 349 nbtr = nqtrue-COUNT(tracers(:)%component == 'lmdz' .AND. delPhase(tracers(:)%gen0Name) == 'H2O') !--- Passed to phytrac 350 nqCO2 = COUNT( [type_trac == 'inco', type_trac == 'co2i'] ) 231 351 #ifdef INCA 232 nqo = SIZE(tracers) - nqCO2 233 CALL Init_chem_inca_trac(nqINCA) !--- Get nqINCA from INCA 234 nbtr = nqINCA + nqCO2 !--- Number of tracers passed to phytrac 235 nqtrue = nbtr + nqo !--- Total number of "true" tracers 236 IF(ALL([2,3] /= nqo)) CALL abort_gcm(modname, 'Only 2 or 3 water phases allowed ; found nqo='//TRIM(int2str(nqo)), 1) 237 ALLOCATE(hadv(nqtrue), hadv_inca(nqINCA), conv_flg_inca(nqINCA), solsym_inca(nqINCA)) 238 ALLOCATE(vadv(nqtrue), vadv_inca(nqINCA), pbl_flg_inca(nqINCA)) 239 CALL init_transport(solsym_inca, conv_flg_inca, pbl_flg_inca, hadv_inca, vadv_inca) 240 ALLOCATE(ttr(nqtrue)) 241 ttr(1:nqo+nqCO2) = tracers 242 ttr(1 : nqo )%component = 'lmdz' 243 ttr(1+nqo:nqCO2+nqo )%component = 'co2i' 244 ttr(1+nqo+nqCO2:nqtrue)%component = 'inca' 245 ttr(1+nqo :nqtrue)%name = [('CO2 ', iq=1, nqCO2), solsym_inca] 246 ttr(1+nqo+nqCO2:nqtrue)%parent = tran0 247 ttr(1+nqo+nqCO2:nqtrue)%phase = 'g' 248 lerr = getKey('hadv', had, ky=tracers(:)%keys) 249 lerr = getKey('vadv', vad, ky=tracers(:)%keys) 250 hadv(1:nqo+nqCO2) = had(:); hadv(1+nqo+nqCO2:nqtrue) = hadv_inca 251 vadv(1:nqo+nqCO2) = vad(:); vadv(1+nqo+nqCO2:nqtrue) = vadv_inca 252 CALL MOVE_ALLOC(FROM=ttr, TO=tracers) 253 DO iq = 1, nqtrue 254 t1 => tracers(iq) 255 CALL addKey('name', t1%name, t1%keys) 256 CALL addKey('component', t1%component, t1%keys) 257 CALL addKey('parent', t1%parent, t1%keys) 258 CALL addKey('phase', t1%phase, t1%keys) 259 END DO 260 IF(setGeneration(tracers)) CALL abort_gcm(modname,'See above',1) !- SET FIELDS %iGeneration, %gen0Name 261 DEALLOCATE(had, hadv_inca, vad, vadv_inca, conv_flg_inca, pbl_flg_inca, solsym_inca) 262 #endif 263 !--------------------------------------------------------------------------------------------------------------------------- 264 ELSE !=== OTHER CASES (OLD OR NEW FORMAT, NO INCA MODULE) 265 !--------------------------------------------------------------------------------------------------------------------------- 266 nqo = COUNT(delPhase(tracers(:)%name) == 'H2O' & 267 .AND. tracers(:)%component == 'lmdz') !--- Number of water phases 268 nqtrue = SIZE(tracers) !--- Total number of "true" tracers 269 nbtr = nqtrue-COUNT(delPhase(tracers(:)%gen0Name) == 'H2O' & 270 .AND. tracers(:)%component == 'lmdz') !--- Number of tracers passed to phytrac 271 #ifdef INCA 272 nqINCA = COUNT(tracers(:)%component == 'inca') 273 #endif 274 lerr = getKey('hadv', hadv, ky=tracers(:)%keys) 275 lerr = getKey('vadv', vadv, ky=tracers(:)%keys) 276 !--------------------------------------------------------------------------------------------------------------------------- 277 END IF 278 !--------------------------------------------------------------------------------------------------------------------------- 279 352 nqINCA = COUNT(tracers(:)%component == 'inca') 353 #endif 280 354 #ifdef REPROBUS 281 !--- Transfert the number of tracers to Reprobus 282 CALL Init_chem_rep_trac(nbtr, nqo, tracers(:)%name) 283 284 #endif 355 CALL Init_chem_rep_trac(nbtr, nqo, tracers(:)%name) !--- Transfert the number of tracers to Reprobus 356 #endif 357 285 358 !============================================================================================================================== 286 359 ! 2) Calculate nqtot, number of tracers needed (greater if advection schemes 20 or 30 have been chosen). 287 360 !============================================================================================================================== 361 IF(getKey('hadv', hadv, ky=tra)) CALL abort_gcm(modname, 'missing key "hadv"', 1) 362 IF(getKey('vadv', vadv, ky=tra)) CALL abort_gcm(modname, 'missing key "vadv"', 1) 288 363 DO iq = 1, nqtrue 289 364 IF( hadv(iq)<20 .OR. (ANY(hadv(iq)==[20,30]) .AND. hadv(iq)==vadv(iq)) ) CYCLE … … 303 378 304 379 !============================================================================================================================== 305 ! 3) Determine the advection scheme choice for water and tracers "iadv" and the fields long name , isAdvected.380 ! 3) Determine the advection scheme choice for water and tracers "iadv" and the fields long name. 306 381 ! iadv = 1 "LMDZ-specific humidity transport" (for H2O vapour) LMV 307 382 ! iadv = 2 backward (for H2O liquid) BAK … … 321 396 !============================================================================================================================== 322 397 ALLOCATE(ttr(nqtot)) 323 jq = nqtrue+1 ; tracers(:)%iadv = -1398 jq = nqtrue+1 324 399 DO iq = 1, nqtrue 325 400 t1 => tracers(iq) … … 332 407 IF(iad == -1) CALL abort_gcm(modname, msg1, 1) 333 408 334 !--- SET FIELDS %longName, %iadv, %isAdvected, %isInPhysics 409 !--- SET FIELDS longName, iadv 410 t1%iadv = iad 335 411 t1%longName = t1%name; IF(iad > 0) t1%longName=TRIM(t1%name)//descrq(iad) 336 t1%iadv = iad337 t1%isAdvected = iad >= 0338 t1%isInPhysics= delPhase(t1%gen0Name) /= 'H2O' &339 .OR. t1%component /= 'lmdz' !=== OTHER EXCEPTIONS TO BE ADDED: CO2i, SURSATURATED WATER CLOUD...340 412 ttr(iq) = t1 341 413 … … 347 419 ttr(jq+1:jq+nm) = t1 348 420 ttr(jq+1:jq+nm)%name = [ (TRIM(t1%name) //'-'//TRIM(suff(im)), im=1, nm) ] 421 ttr(jq+1:jq+nm)%gen0Name = [ (TRIM(t1%name) //'-'//TRIM(suff(im)), im=1, nm) ] 349 422 ttr(jq+1:jq+nm)%parent = [ (TRIM(t1%parent) //'-'//TRIM(suff(im)), im=1, nm) ] 350 423 ttr(jq+1:jq+nm)%longName = [ (TRIM(t1%longName)//'-'//TRIM(suff(im)), im=1, nm) ] 351 424 ttr(jq+1:jq+nm)%iadv = [ (-iad, im=1, nm) ] 352 ttr(jq+1:jq+nm)%isAdvected = [ (.FALSE., im=1, nm) ]353 425 jq = jq + nm 354 426 END DO … … 356 428 CALL MOVE_ALLOC(FROM=ttr, TO=tracers) 357 429 358 !--- SET FIELDS %iqParent, %nqChildren, %iGeneration, %iqDescen, %nqDescen 359 IF(indexUpdate(tracers)) CALL abort_gcm(modname, 'problem with tracers indices update', 1) 430 !--- SET FIELDS iqParent, iqDescen, nqDescen, nqChildren 431 IF(indexUpdate(tracers%keys)) CALL abort_gcm(modname, 'problem with tracers indices update', 1) 432 k => tracers(:)%keys 433 DO iq = 1, SIZE(tracers); t1 => tracers(iq); msg1 = '" for "'//TRIM(t1%name)//'"' 434 ky='iqParent '; IF(getKey(ky, t1%iqParent, iq, k)) CALL abort_gcm(modname, 'missing key "'//TRIM(ky)//TRIM(msg1), 1) 435 ky='iqDescen '; IF(getKey(ky, t1%iqDescen, iq, k)) CALL abort_gcm(modname, 'missing key "'//TRIM(ky)//TRIM(msg1), 1) 436 ky='nqDescen '; IF(getKey(ky, t1%nqDescen, iq, k)) CALL abort_gcm(modname, 'missing key "'//TRIM(ky)//TRIM(msg1), 1) 437 ky='nqChildren'; IF(getKey(ky, t1%nqChildren, iq, k)) CALL abort_gcm(modname, 'missing key "'//TRIM(ky)//TRIM(msg1), 1) 438 END DO 360 439 361 440 !=== TEST ADVECTION SCHEME 362 DO iq=1,nqtot ; t1 => tracers(iq); iad = t1%iadv 441 DO iq = 1, nqtot ; t1 => tracers(iq) 442 iad = t1%iadv 443 ig = t1%iGeneration 444 nam = t1%name 445 val = 'iadv='//TRIM(int2str(iad)) 363 446 364 447 !--- ONLY TESTED VALUES FOR TRACERS FOR NOW: iadv = 14, 10 (and 0 for non-transported tracers) 365 IF(ALL([10,14,0] /= iad)) & 366 CALL abort_gcm(modname, 'Not tested for iadv='//TRIM(int2str(iad))//' ; 10 or 14 only are allowed !', 1) 367 368 !--- ONLY TESTED VALUES FOR PARENTS HAVING CHILDS FOR NOW: iadv = 14, 10 (PARENTS: TRACERS OF GENERATION 1) 369 IF(ALL([10,14] /= iad) .AND. t1%iGeneration == 1 .AND. ANY(tracers(:)%iGeneration > 1)) & 370 CALL abort_gcm(modname, 'iadv='//TRIM(int2str(iad))//' not implemented for parents ; 10 or 14 only are allowed !', 1) 371 372 !--- ONLY TESTED VALUES FOR CHILDS FOR NOW: iadv = 10 (CHILDS: TRACERS OF GENERATION GREATER THAN 1) 373 IF(fmsg('WARNING ! iadv='//TRIM(int2str(iad))//' not implemented for childs. Setting iadv=10 for "'//TRIM(t1%name)//'"',& 374 modname, iad /= 10 .AND. t1%iGeneration > 1)) t1%iadv = 10 375 376 !--- ONLY VALID SCHEME NUMBER FOR WATER VAPOUR: iadv = 14 377 ll = t1%name /= addPhase('H2O','g') 378 IF(fmsg('WARNING ! iadv=14 is valid for water vapour only. Setting iadv=10 for "'//TRIM(t1%name)//'".', & 379 modname, iad == 14 .AND. ll)) t1%iadv = 10 448 IF(ALL([10,14,0] /= iad)) CALL abort_gcm(modname, TRIM(val)//' has not been tested yet ; 10 or 14 only are allowed !', 1) 449 450 !--- ONLY TESTED VALUES SO FAR FOR PARENTS HAVING CHILDREN: iadv = 14, 10 (PARENTS: TRACERS OF GENERATION 0) 451 IF(ALL([10,14] /= iad) .AND. ig == 0 .AND. ANY(tracers(:)%parent==nam)) & 452 CALL abort_gcm(modname, TRIM(val)//' is not implemented for parents ; 10 or 14 only are allowed !', 1) 453 454 !--- ONLY TESTED VALUES SO FAR FOR DESCENDANTS (TRACERS OF GENERATION > 0): iadv = 10 ; WATER VAPOUR: iadv = 14 455 lerr = iad /= 10 .AND. ig > 0; IF(lerr) tracers(iq)%iadv = 10 456 CALL msg('WARNING! '//TRIM(val)// ' not implemented for children. Setting iadv=10 for "'//TRIM(nam)//'"', modname, lerr) 457 lerr = iad == 14 .AND. nam /= addPhase('H2O','g'); IF(lerr) tracers(iq)%iadv = 10 458 CALL msg('WARNING! '//TRIM(val)//' is valid for water vapour only. Setting iadv=10 for "'//TRIM(nam)//'"', modname, lerr) 380 459 END DO 381 460 382 !=== READ PHYSICAL PARAMETERS FOR ISOTOPES ; DONE HERE BECAUSE dynetat0 AND iniacademic NEED "tnat" AND "alpha_ideal" 383 niso = 0; nzone = 0; nphas = nqo; ntiso = 0; isoCheck = .FALSE. 384 IF(processIsotopes()) CALL abort_gcm(modname, 'problem when processing isotopes parameters', 1) 461 !=== DETERMINE ISOTOPES RELATED PARAMETERS ; DEFINE THE EXPLICIT KEYS iso_i* 462 IF(processIsotopes(tracers%keys, iso)) CALL abort_gcm(modname, 'problem while processing isotopes parameters', 1) 463 464 !--- POPULATE SOME EXPLICIT (ACCESSIBLE THROUGH "%") KEYS OF THE LOCAL ISOTOPES DESCRIPTION DERIVED TYPE 465 nbIso = SIZE(iso) 466 ALLOCATE(isotopes(nbIso)) 467 IF(nbIso /= 0) THEN 468 k => tracers(:)%keys 469 IF(getKey('iso_iGroup', itmp, ky=k)) CALL abort_gcm(modname, 'missing key "iso_iGroup"', 1); tracers%iso_iGroup=itmp 470 IF(getKey('iso_iName', itmp, ky=k)) CALL abort_gcm(modname, 'missing key "iso_iName"', 1); tracers%iso_iName =itmp 471 IF(getKey('iso_iZone', itmp, ky=k)) CALL abort_gcm(modname, 'missing key "iso_iZone"', 1); tracers%iso_iZone =itmp 472 IF(getKey('iso_iPhas', itmp, ky=k)) CALL abort_gcm(modname, 'missing key "iso_iPhas"', 1); tracers%iso_iPhase=itmp 473 isotopes(:)%name = iso(:)%name !--- Isotopes family name (ex: H2O) 474 isotopes(:)%phase = iso(:)%phase !--- Phases list: [g][l][s] (length: nphas) 475 isotopes(:)%niso = iso(:)%niso !--- Number of isotopes, excluding tagging tracers 476 isotopes(:)%ntiso = iso(:)%ntiso !--- Number of isotopes, including tagging tracers 477 isotopes(:)%nzone = iso(:)%nzone !--- Number of geographic tagging zones 478 isotopes(:)%nphas = iso(:)%nphas !--- Number of phases 479 isotopes(:)%check = .FALSE. !--- Flag for checking routines triggering 480 CALL getin('ok_iso_verif', isotopes(:)%check) 481 DO it = 1, nbIso 482 isotopes(it)%keys = iso(it)%keys !--- Isotopes keys/values pairs list (length: niso) 483 isotopes(it)%trac = iso(it)%trac !--- Isotopes + tagging tracers list (length: ntiso) 484 isotopes(it)%zone = iso(it)%zone !--- Geographic tagging zones names list (length: nzone) 485 isotopes(it)%iqIsoPha = iso(it)%iqIsoPha(:,:) !--- Idx in "tracers(1:nqtot)" = f(name(1:ntiso)),phas) 486 isotopes(it)%itZonIso = iso(it)%itZonIso(:,:) !--- Idx in "tracers(1:ntiso)" = f( zone,name(1:niso)) 487 END DO 488 IF(isoSelect(1, .TRUE.)) CALL abort_gcm(modname, "Can't select the first isotopes family", 1) 489 IF(.NOT.isoSelect('H2O', .TRUE.)) iH2O = ixIso 490 END IF 491 isoFamilies = isotopes(:)%name 385 492 386 493 !--- Convection / boundary layer activation for all tracers 387 ALLOCATE(conv_flg(nbtr)); conv_flg(1:nbtr) = 1388 ALLOCATE( pbl_flg(nbtr)); pbl_flg(1:nbtr) = 1494 IF(.NOT.ALLOCATED(conv_flg)) ALLOCATE(conv_flg(nbtr)); conv_flg(1:nbtr) = 1 495 IF(.NOT.ALLOCATED( pbl_flg)) ALLOCATE( pbl_flg(nbtr)); pbl_flg(1:nbtr) = 1 389 496 390 497 !--- Note: nqtottr can differ from nbtr when nmom/=0 … … 394 501 395 502 !=== DISPLAY THE RESULTS 503 IF(.NOT.is_master) RETURN 396 504 CALL msg('nqo = '//TRIM(int2str(nqo)), modname) 397 505 CALL msg('nbtr = '//TRIM(int2str(nbtr)), modname) … … 405 513 #endif 406 514 t => tracers 407 CALL msg('Information stored in infotrac :', modname) 408 409 IF(dispTable('isssssssssiiiiiiiii', ['iq ', 'name', 'lNam', 'g0Nm', 'prnt', 'type', 'phas', 'comp', & 410 'isPh', 'isAd', 'iadv', 'iGen', 'iqPr', 'nqDe', 'nqCh', 'iGrp', 'iNam', 'iZon', 'iPha'], & 411 cat(t%name, t%longName, t%gen0Name, t%parent, t%type, t%phase, t%component, bool2str(t%isInPhysics), & 412 bool2str(t%isAdvected)), & 515 CALL msg('Information stored in '//TRIM(modname)//': ', modname) 516 IF(dispTable('isssssssiiiiiiiii', ['iq ', 'name', 'lNam', 'g0Nm', 'prnt', 'type', 'phas', 'comp', & 517 'iAdv', 'iGen', 'iqPr', 'nqDe', 'nqCh', 'iGrp', 'iNam', 'iZon', 'iPha'], & 518 cat(t%name, t%longName, t%gen0Name, t%parent, t%type, t%phase, t%component), & 413 519 cat([(iq, iq=1, nqtot)], t%iadv, t%iGeneration, t%iqParent, t%nqDescen, t%nqChildren, t%iso_iGroup, & 414 520 t%iso_iName, t%iso_iZone, t%iso_iPhase), nColMax=maxTableWidth, nHead=2, sub=modname)) & 415 521 CALL abort_gcm(modname, "problem with the tracers table content", 1) 416 IF(niso > 0) THEN 417 CALL msg('Where, for isotopes family "'//TRIM(isotope%parent)//'":', modname) 418 CALL msg(' isoKeys%name = '//strStack(isoKeys%name), modname) 419 CALL msg(' isoName = '//strStack(isoName), modname) 420 CALL msg(' isoZone = '//strStack(isoZone), modname) 421 CALL msg(' isoPhas = '//TRIM(isoPhas), modname) 522 CALL msg('No isotopes identified.', modname, nbIso == 0) 523 IF(nbIso == 0) RETURN 524 DO it = 1, nbIso 525 IF(isoSelect(it, .TRUE.)) CALL abort_gcm(modname, 'Problem when selecting isotopes class', 1) 526 CALL msg('For isotopes family "'//TRIM(isoFamilies(it))//'":', modname) 527 CALL msg(' isoName = '//strStack(isotope%trac), modname) 528 CALL msg(' isoZone = '//strStack(isotope%zone), modname) 529 CALL msg(' isoPhas = '// TRIM(isotope%phase), modname) 530 END DO 531 IF(isoSelect('H2O', .TRUE.)) THEN 532 IF(isoSelect(1, .TRUE.)) CALL abort_gcm(modname, 'Problem when selecting isotopes class', 1) 422 533 ELSE 423 CALL msg('No isotopes identified.', modname)534 iH2O = ixIso 424 535 END IF 425 CALL msg('end', modname) 536 IF(ALLOCATED(isotope%keys(ixIso)%key)) & 537 CALL msg(' isoKeys('//TRIM(int2str(ixIso))//') = '//TRIM(strStack(isotope%keys(ixIso)%key)), modname) 426 538 427 539 END SUBROUTINE init_infotrac 428 540 541 !============================================================================================================================== 542 LOGICAL FUNCTION isoSelectByName(iClass, lVerbose) RESULT(lerr) 543 IMPLICIT NONE 544 CHARACTER(LEN=*), INTENT(IN) :: iClass 545 LOGICAL, OPTIONAL, INTENT(IN) :: lVerbose 546 INTEGER :: iIso 547 LOGICAL :: lV 548 lV = .FALSE.; IF(PRESENT(lVerbose)) lV = lVerbose 549 iIso = strIdx(isotopes(:)%name, iClass) 550 lerr = iIso == 0 551 IF(lerr) THEN 552 niso = 0; ntiso = 0; nzone = 0; nphas = 0; isoCheck=.FALSE. 553 CALL msg('no isotope family named "'//TRIM(iClass)//'"', ll=lV) 554 RETURN 555 END IF 556 lerr = isoSelectByIndex(iIso, lV) 557 END FUNCTION isoSelectByName 558 !============================================================================================================================== 559 LOGICAL FUNCTION isoSelectByIndex(iIso, lVerbose) RESULT(lerr) 560 IMPLICIT NONE 561 INTEGER, INTENT(IN) :: iIso 562 LOGICAL, OPTIONAL, INTENT(IN) :: lVerbose 563 LOGICAL :: lV 564 lV = .FALSE.; IF(PRESENT(lVerbose)) lV = lVerbose 565 lerr = .FALSE. 566 IF(iIso == ixIso) RETURN !--- Nothing to do if the index is already OK 567 lerr = iIso<=0 .OR. iIso>SIZE(isotopes) 568 CALL msg('Inconsistent isotopes family index '//TRIM(int2str(iIso))//': should be > 0 and <= '& 569 //TRIM(int2str(SIZE(isotopes)))//'"', ll = lerr .AND. lV) 570 IF(lerr) RETURN 571 ixIso = iIso !--- Update currently selected family index 572 isotope => isotopes(ixIso) !--- Select corresponding component 573 isoKeys => isotope%keys; niso = isotope%niso 574 isoName => isotope%trac; ntiso = isotope%ntiso 575 isoZone => isotope%zone; nzone = isotope%nzone 576 isoPhas => isotope%phase; nphas = isotope%nphas 577 itZonIso => isotope%itZonIso; isoCheck = isotope%check 578 iqIsoPha => isotope%iqIsoPha 579 END FUNCTION isoSelectByIndex 580 !============================================================================================================================== 581 429 582 END MODULE infotrac -
LMDZ6/trunk/libf/dyn3d_common/iso_verif_dyn.F
r4325 r5183 64 64 function iso_verif_aberrant_nostop 65 65 : (x,iso,q,err_msg) 66 USE infotrac, ONLY: isoName, getKey 66 #ifdef CPP_IOIPSL 67 USE IOIPSL, ONLY: getin 68 #else 69 USE ioipsl_getincom, ONLY: getin 70 #endif 71 USE iso_params_mod, ONLY: tnat_HDO 67 72 implicit none 68 73 … … 74 79 ! locals 75 80 real qmin,deltaD 76 real deltaDmax,deltaDmin ,tnat81 real deltaDmax,deltaDmin 77 82 parameter (qmin=1e-11) 78 83 parameter (deltaDmax=200.0,deltaDmin=-999.9) 84 LOGICAL :: ltnat1 85 LOGICAL, SAVE :: lFirst=.TRUE. 86 REAL, SAVE :: tnat 79 87 80 88 ! output 81 89 integer iso_verif_aberrant_nostop 82 90 91 IF(lFirst) THEN 92 ltnat1 = .TRUE.; CALL getin('tnateq1', ltnat1) 93 tnat = tnat_HDO; IF(ltnat1) tnat = 1.0 94 lFirst = .FALSE. 95 END IF 83 96 iso_verif_aberrant_nostop=0 84 97 85 98 ! verifier que HDO est raisonable 86 99 if (q.gt.qmin) then 87 IF(getKey('tnat', tnat, isoName(iso))) THEN88 err_msg = 'Missing isotopic parameter "tnat"'89 iso_verif_aberrant_nostop=190 RETURN91 END IF92 100 deltaD=(x/q/tnat-1)*1000 93 101 if ((deltaD.gt.deltaDmax).or.(deltaD.lt.deltaDmin)) then -
LMDZ6/trunk/libf/dyn3dmem/check_isotopes_loc.F90
r4984 r5183 3 3 USE strings_mod, ONLY: maxlen, msg, strIdx, strStack, int2str, real2str 4 4 USE infotrac, ONLY: nqtot, niso, nphas, isotope, isoCheck, iqIsoPha, isoSelect, & 5 ntiso, iH2O, nzone, tracers, isoName, itZonIso, getKey 5 ntiso, iH2O, nzone, tracers, isoName, itZonIso 6 USE iso_params_mod, ONLY: tnat_H216O, tnat_H217O, tnat_H218O, tnat_HDO, tnat_HTO 7 #ifdef CPP_IOIPSL 8 USE ioipsl, ONLY: getin 9 #else 10 USE ioipsl_getincom, ONLY: getin 11 #endif 6 12 IMPLICIT NONE 7 13 include "dimensions.h" … … 21 27 deltaDmin =-999.0, & 22 28 ridicule = 1e-12 23 INTEGER, SAVE :: iso_eau, iso_HDO, iso_O18, & !--- OpenMP shared variables 24 iso_O17, iso_HTO 29 INTEGER, SAVE :: iso_eau, iso_HDO, iso_O18, iso_O17, iso_HTO 30 !$OMP THREADPRIVATE(iso_eau, iso_HDO, iso_O18, iso_O17, iso_HTO) 31 LOGICAL :: ltnat1 25 32 LOGICAL, SAVE :: first=.TRUE. 26 LOGICAL, PARAMETER :: tnat1=.TRUE.27 33 !$OMP THREADPRIVATE(first) 28 34 … … 32 38 IF(niso == 0) RETURN !--- No isotopes => finished 33 39 IF(first) THEN 34 !$OMP MASTER 35 iso_eau = strIdx(isoName,'H216O') 36 iso_HDO = strIdx(isoName,'HDO') 37 iso_O18 = strIdx(isoName,'H218O') 38 iso_O17 = strIdx(isoName,'H217O') 39 iso_HTO = strIdx(isoName,'HTO') 40 if (tnat1) then 41 tnat(:)=1.0 42 else 43 IF(getKey('tnat', tnat)) CALL abort_gcm(modname, 'missing isotopic parameter', 1) 44 endif 45 !$OMP END MASTER 46 !$OMP BARRIER 40 ltnat1 = .TRUE.; CALL getin('tnateq1', ltnat1) 41 iso_eau = strIdx(isoName,'H216O'); IF(iso_eau /= 0) tnat(iso_eau) = tnat_H216O 42 iso_O17 = strIdx(isoName,'H217O'); IF(iso_O17 /= 0) tnat(iso_O17) = tnat_H217O 43 iso_O18 = strIdx(isoName,'H218O'); IF(iso_O18 /= 0) tnat(iso_O18) = tnat_H218O 44 iso_HDO = strIdx(isoName,'HDO'); IF(iso_HDO /= 0) tnat(iso_HDO) = tnat_HDO 45 iso_HTO = strIdx(isoName,'HTO'); IF(iso_HTO /= 0) tnat(iso_HTO) = tnat_HTO 46 IF(ltnat1) tnat(:) = 1.0 47 47 first = .FALSE. 48 48 END IF -
LMDZ6/trunk/libf/dyn3dmem/dynetat0_loc.F90
r5084 r5183 7 7 !------------------------------------------------------------------------------- 8 8 USE parallel_lmdz 9 USE infotrac, ONLY: nqtot, tracers, niso, iqIsoPha, iH2O, isoName 9 USE infotrac, ONLY: nqtot, tracers, niso, iqIsoPha, iH2O, isoName, & 10 new2oldH2O, newHNO3, oldHNO3 10 11 USE strings_mod, ONLY: maxlen, msg, strStack, real2str, int2str, strIdx 11 12 USE netcdf, ONLY: NF90_OPEN, NF90_NOWRITE, NF90_INQUIRE_DIMENSION, NF90_INQ_VARID, & 12 13 NF90_CLOSE, NF90_GET_VAR, NF90_INQUIRE_VARIABLE, NF90_NoErr 13 USE readTracFiles_mod, ONLY: new2oldH2O, newHNO3, oldHNO3, getKey14 14 USE control_mod, ONLY: planet_type 15 15 USE assert_eq_m, ONLY: assert_eq … … 20 20 USE temps_mod, ONLY: annee_ref, day_ini, day_ref, itau_dyn, start_time 21 21 USE ener_mod, ONLY: etot0,ptot0,ztot0,stot0,ang0 22 #ifdef CPP_IOIPSL 23 USE IOIPSL, ONLY: getin 24 #else 25 USE ioipsl_getincom, ONLY: getin 26 #endif 27 USE iso_params_mod ! tnat_* and alpha_ideal_* 22 28 23 29 IMPLICIT NONE … … 47 53 REAL, ALLOCATABLE :: ucov_glo(:,:), q_glo(:,:), phis_glo(:) 48 54 REAL, ALLOCATABLE :: teta_glo(:,:) 49 LOGICAL :: lSkip, ll 50 LOGICAL,PARAMETER :: tnat1=.TRUE. 55 LOGICAL :: lSkip, ll, ltnat1 51 56 !------------------------------------------------------------------------------- 52 57 modname="dynetat0_loc" … … 158 163 ll = NF90_INQ_VARID(fID, 'HNO3tot', vID) /= NF90_NoErr !--- DETECT OLD REPRO start.nc FILE 159 164 #endif 165 ltnat1 = .TRUE.; CALL getin('tnateq1', ltnat1) 160 166 DO iq=1,nqtot 161 167 var = tracers(iq)%name … … 173 179 !-------------------------------------------------------------------------------------------------------------------------- 174 180 ELSE IF(NF90_INQ_VARID(fID, oldVar, vID) == NF90_NoErr) THEN !=== TRY WITH ALTERNATE NAME 175 CALL msg(' Tracer <'//TRIM(var)//'> is missing=> initialized to <'//TRIM(oldVar)//'>', modname)181 CALL msg('Missing tracer <'//TRIM(var)//'> => initialized to <'//TRIM(oldVar)//'>', modname) 176 182 CALL get_var2(oldVar, q_glo); q(ijb_u:ije_u,:,iq)=q_glo(ijb_u:ije_u,:) 177 183 !-------------------------------------------------------------------------------------------------------------------------- … … 181 187 iqParent = tracers(iq)%iqParent 182 188 IF(tracers(iq)%iso_iZone == 0) THEN 183 if (tnat1) then 184 tnat=1.0 185 alpha_ideal=1.0 186 write(*,*) 'attention dans dynetat0: les alpha_ideal sont a 1' 187 else 188 IF(getKey('tnat', tnat, isoName(iName)) .OR. getKey('alpha', alpha_ideal, isoName(iName))) & 189 CALL abort_gcm(TRIM(modname), 'missing isotopic parameters', 1) 190 endif 191 CALL msg('Tracer <'//TRIM(var)//'> is missing => initialized with a simplified Rayleigh distillation law.', modname) 189 IF(ltnat1) THEN 190 tnat = 1.0 191 alpha_ideal = 1.0 192 CALL msg(' !!! Beware: alpha_ideal put to 1 !!!', modname) 193 ELSE 194 SELECT CASE(isoName(iName)) 195 CASE('H216O'); tnat = tnat_H216O; alpha_ideal = alpha_ideal_H216O 196 CASE('H217O'); tnat = tnat_H217O; alpha_ideal = alpha_ideal_H217O 197 CASE('H218O'); tnat = tnat_H218O; alpha_ideal = alpha_ideal_H218O 198 CASE('HDO'); tnat = tnat_HDO; alpha_ideal = alpha_ideal_HDO 199 CASE('HTO'); tnat = tnat_HTO; alpha_ideal = alpha_ideal_HTO 200 CASE DEFAULT; CALL abort_gcm(TRIM(modname),'unknown isotope "'//TRIM(isoName(iName))//'" ; check tracer.def file',1) 201 END SELECT 202 END IF 203 CALL msg('Missing tracer <'//TRIM(var)//'> => initialized with a simplified Rayleigh distillation law.', modname) 192 204 q(ijb_u:ije_u,:,iq) = q(ijb_u:ije_u,:,iqParent)*tnat*(q(ijb_u:ije_u,:,iqParent)/30.e-3)**(alpha_ideal-1.) 193 205 ! Camille 9 mars 2023: point de vigilence: initialisation incohérente 194 206 ! avec celle de xt_ancien dans la physiq. 195 207 ELSE 196 CALL msg(' Tracer <'//TRIM(var)//'> is missing=> initialized to its parent isotope concentration.', modname)208 CALL msg('Missing tracer <'//TRIM(var)//'> => initialized to its parent isotope concentration.', modname) 197 209 ! Camille 9 mars 2023: attention!! seuls les tags qui correspondent à 198 210 ! izone=izone_init (définie dans isotrac_mod) sont initialisés comme … … 208 220 !-------------------------------------------------------------------------------------------------------------------------- 209 221 ELSE !=== MISSING: SET TO 0 210 CALL msg(' Tracer <'//TRIM(var)//'> is missing=> initialized to zero', modname)222 CALL msg('missing tracer <'//TRIM(var)//'> => initialized to zero', modname) 211 223 q(ijb_u:ije_u,:,iq)=0. 212 224 !-------------------------------------------------------------------------------------------------------------------------- -
LMDZ6/trunk/libf/dyn3dmem/iniacademic_loc.F90
r5084 r5183 5 5 6 6 USE filtreg_mod, ONLY: inifilr 7 USE infotrac, ONLY: nqtot, niso, iqIsoPha, tracers, getKey, isoName7 USE infotrac, ONLY: nqtot, niso, iqIsoPha, tracers, addPhase, isoName 8 8 USE control_mod, ONLY: day_step,planet_type 9 9 use exner_hyb_m, only: exner_hyb … … 22 22 USE temps_mod, ONLY: annee_ref, day_ini, day_ref 23 23 USE ener_mod, ONLY: etot0,ptot0,ztot0,stot0,ang0 24 USE readTracFiles_mod, ONLY: addPhase25 24 use netcdf, only : NF90_NOWRITE,NF90_OPEN,NF90_NOERR,NF90_INQ_VARID 26 25 use netcdf, only : NF90_CLOSE, NF90_GET_VAR 26 USE iso_params_mod ! tnat_* and alpha_ideal_* 27 27 28 28 … … 85 85 86 86 REAL zdtvr, tnat, alpha_ideal 87 LOGICAL ,PARAMETER :: tnat1=.true.87 LOGICAL :: ltnat1 88 88 89 89 character(len=*),parameter :: modname="iniacademic" … … 311 311 ! bulk initialization of tracers 312 312 if (planet_type=="earth") then 313 ltnat1 = .TRUE.; CALL getin('tnateq1', ltnat1) 313 314 ! Earth: first two tracers will be water 314 315 do iq=1,nqtot … … 324 325 iqParent = tracers(iq)%iqParent 325 326 IF(tracers(iq)%iso_iZone == 0) THEN 326 if (tnat1) then 327 tnat=1.0 328 alpha_ideal=1.0 329 write(*,*) 'Attention dans iniacademic: alpha_ideal=1' 330 else 331 IF(getKey('tnat', tnat, isoName(iName)) .OR. getKey('alpha', alpha_ideal, isoName(iName))) & 332 CALL abort_gcm(TRIM(modname), 'missing isotopic parameters', 1) 333 endif 327 IF(ltnat1) THEN 328 tnat = 1.0 329 alpha_ideal = 1.0 330 WRITE(lunout, *) 'In '//TRIM(modname)//': !!! Beware: alpha_ideal put to 1 !!!' 331 ELSE 332 SELECT CASE(isoName(iName)) 333 CASE('H216O'); tnat = tnat_H216O; alpha_ideal = alpha_ideal_H216O 334 CASE('H217O'); tnat = tnat_H217O; alpha_ideal = alpha_ideal_H217O 335 CASE('H218O'); tnat = tnat_H218O; alpha_ideal = alpha_ideal_H218O 336 CASE('HDO'); tnat = tnat_HDO; alpha_ideal = alpha_ideal_HDO 337 CASE('HTO'); tnat = tnat_HTO; alpha_ideal = alpha_ideal_HTO 338 CASE DEFAULT 339 CALL abort_gcm(TRIM(modname),'unknown isotope "'//TRIM(isoName(iName))//'" ; check tracer.def file',1) 340 END SELECT 341 END IF 334 342 q(ijb_u:ije_u,:,iq) = q(ijb_u:ije_u,:,iqParent)*tnat*(q(ijb_u:ije_u,:,iqParent)/30.e-3)**(alpha_ideal-1.) 335 343 ELSE !IF(tracers(iq)%iso_iZone == 0) THEN -
LMDZ6/trunk/libf/dyn3dmem/qminimum_loc.F
r5001 r5183 4 4 SUBROUTINE qminimum_loc( q,nqtot,deltap ) 5 5 USE parallel_lmdz 6 USE infotrac, ONLY: niso, ntiso, iqIsoPha, tracers, 6 USE infotrac, ONLY: niso, ntiso, iqIsoPha, tracers, addPhase, 7 7 & isoCheck, min_qParent 8 8 USE strings_mod, ONLY: strIdx 9 USE readTracFiles_mod, ONLY: addPhase10 9 IMPLICIT none 11 10 c -
LMDZ6/trunk/libf/dynphy_lonlat/calfis.F
r4464 r5183 29 29 c Auteur : P. Le Van, F. Hourdin 30 30 c ......... 31 USE infotrac , ONLY: nqtot, tracers31 USE infotrac_phy, ONLY: nqtot, tracers 32 32 USE control_mod, ONLY: planet_type, nsplit_phys 33 33 #ifdef CPP_PHYS -
LMDZ6/trunk/libf/dynphy_lonlat/calfis_loc.F
r5084 r5183 47 47 USE Times 48 48 #endif 49 USE infotrac , ONLY: nqtot, tracers49 USE infotrac_phy, ONLY: nqtot, tracers 50 50 USE control_mod, ONLY: planet_type, nsplit_phys 51 51 #ifdef CPP_PHYS -
LMDZ6/trunk/libf/misc/readTracFiles_mod.f90
r5005 r5183 10 10 11 11 PUBLIC :: maxlen !--- PARAMETER FOR CASUAL STRING LENGTH 12 PUBLIC :: trac_type, tracers, setGeneration, indexUpdate !--- TRACERS DESCRIPTION DATABASE + ASSOCIATED TOOLS12 PUBLIC :: keys_type, tracers, setGeneration, indexUpdate !--- TRACERS DESCRIPTION DATABASE + ASSOCIATED TOOLS 13 13 PUBLIC :: testTracersFiles, readTracersFiles !--- TRACERS FILES READING ROUTINES 14 14 PUBLIC :: getKeysDBase, setKeysDBase !--- TOOLS TO GET/SET THE DATABASE (tracers & isotopes) 15 15 PUBLIC :: addTracer, delTracer !--- ADD/REMOVE A TRACER FROM 16 PUBLIC :: addKey, delKey, getKey , keys_type!--- TOOLS TO SET/DEL/GET KEYS FROM/TO tracers & isotopes16 PUBLIC :: addKey, delKey, getKey !--- TOOLS TO SET/DEL/GET KEYS FROM/TO tracers & isotopes 17 17 PUBLIC :: addPhase, delPhase, getPhase, getiPhase, & !--- FUNCTIONS RELATED TO THE PHASES 18 18 nphases, old_phases, phases_sep, known_phases, phases_names !--- + ASSOCIATED VARIABLES … … 35 35 PUBLIC :: itZonIso !--- Idx IN isoName(1:niso) = f(tagging idx, isotope idx) 36 36 PUBLIC :: iqIsoPha !--- Idx IN qx(1:nqtot) = f(isotope idx, phase idx) 37 PUBLIC :: iqWIsoPha !--- Idx IN qx(1:nqtot) = f(isotope idx, phase idx) but with normal water first37 PUBLIC :: iqWIsoPha !--- SAME AS iqIsoPha BUT ISOTOPES LIST STARTS WITH PARENT TRAC 38 38 PUBLIC :: isoCheck !--- FLAG TO RUN ISOTOPES CHECKING ROUTINES 39 39 … … 41 41 !------------------------------------------------------------------------------------------------------------------------------ 42 42 TYPE :: keys_type !=== TYPE FOR A SET OF KEYS ASSOCIATED TO AN ELEMENT 43 CHARACTER(LEN=maxlen) :: name !--- Tracer name44 43 CHARACTER(LEN=maxlen), ALLOCATABLE :: key(:) !--- Keys string list 45 44 CHARACTER(LEN=maxlen), ALLOCATABLE :: val(:) !--- Corresponding values string list 46 45 END TYPE keys_type 47 46 !------------------------------------------------------------------------------------------------------------------------------ 48 TYPE :: trac_type !=== TYPE FOR A SINGLE TRACER NAMED "name" 49 CHARACTER(LEN=maxlen) :: name = '' !--- Name of the tracer 50 TYPE(keys_type) :: keys !--- <key>=<val> pairs vector 51 CHARACTER(LEN=maxlen) :: gen0Name = '' !--- First generation ancestor name 52 CHARACTER(LEN=maxlen) :: parent = '' !--- Parent name 53 CHARACTER(LEN=maxlen) :: longName = '' !--- Long name (with advection scheme suffix) 54 CHARACTER(LEN=maxlen) :: type = 'tracer' !--- Type (so far: 'tracer' / 'tag') 55 CHARACTER(LEN=maxlen) :: phase = 'g' !--- Phase ('g'as / 'l'iquid / 's'olid) 56 CHARACTER(LEN=maxlen) :: component = '' !--- Coma-separated list of components (Ex: lmdz,inca) 57 INTEGER :: iGeneration = -1 !--- Generation number (>=0) 58 INTEGER :: iqParent = 0 !--- Parent index 59 INTEGER, ALLOCATABLE :: iqDescen(:) !--- Descendants index (in growing generation order) 60 INTEGER :: nqDescen = 0 !--- Number of descendants (all generations) 61 INTEGER :: nqChildren = 0 !--- Number of children (first generation) 62 INTEGER :: iadv = 10 !--- Advection scheme used 63 LOGICAL :: isAdvected = .FALSE. !--- "true" tracers: iadv > 0. COUNT(isAdvected )=nqtrue 64 LOGICAL :: isInPhysics = .TRUE. !--- "true" tracers: in tr_seri. COUNT(isInPhysics)=nqtottr 65 INTEGER :: iso_iGroup = 0 !--- Isotopes group index in isotopes(:) 66 INTEGER :: iso_iName = 0 !--- Isotope name index in isotopes(iso_iGroup)%trac(:) 67 INTEGER :: iso_iZone = 0 !--- Isotope zone index in isotopes(iso_iGroup)%zone(:) 68 INTEGER :: iso_iPhase = 0 !--- Isotope phase index in isotopes(iso_iGroup)%phase 69 END TYPE trac_type 70 !------------------------------------------------------------------------------------------------------------------------------ 71 TYPE :: isot_type !=== TYPE FOR AN ISOTOPES FAMILY DESCENDING ON TRACER "parent" 72 CHARACTER(LEN=maxlen) :: parent !--- Isotopes family name (parent tracer name ; ex: H2O) 47 TYPE :: isot_type !=== TYPE FOR AN ISOTOPES FAMILY DESCENDING ON TRACER "name" 48 CHARACTER(LEN=maxlen) :: name !--- Isotopes family name (example: H2O) 73 49 TYPE(keys_type), ALLOCATABLE :: keys(:) !--- Isotopes keys/values pairs list (length: niso) 74 50 LOGICAL :: check=.FALSE. !--- Flag for checking routines triggering … … 88 64 TYPE :: dataBase_type !=== TYPE FOR TRACERS SECTION 89 65 CHARACTER(LEN=maxlen) :: name !--- Section name 90 TYPE( trac_type), ALLOCATABLE :: trac(:) !--- Tracers descriptors66 TYPE(keys_type), ALLOCATABLE :: trac(:) !--- Tracers descriptors 91 67 END TYPE dataBase_type 92 68 !------------------------------------------------------------------------------------------------------------------------------ … … 139 115 140 116 !=== TRACERS AND ISOTOPES DESCRIPTORS, USED BY getKey 141 TYPE( trac_type), ALLOCATABLE, TARGET, SAVE :: tracers(:)117 TYPE(keys_type), ALLOCATABLE, TARGET, SAVE :: tracers(:) 142 118 TYPE(isot_type), ALLOCATABLE, TARGET, SAVE :: isotopes(:) 143 119 … … 193 169 !------------------------------------------------------------------------------------------------------------------------------ 194 170 CHARACTER(LEN=*), INTENT(IN) :: type_trac !--- List of components used 195 TYPE( trac_type), ALLOCATABLE, TARGET, OPTIONAL, INTENT(OUT) :: tracs(:) !--- Tracers descriptor for external storage171 TYPE(keys_type), ALLOCATABLE, TARGET, OPTIONAL, INTENT(OUT) :: tracs(:) !--- Tracers descriptor for external storage 196 172 LOGICAL, OPTIONAL, INTENT(IN) :: lRepr !--- Activate the HNO3 exceptions for REPROBUS 197 173 CHARACTER(LEN=maxlen), ALLOCATABLE :: s(:), sections(:), trac_files(:) 198 CHARACTER(LEN=maxlen) :: str, fname, tname, pname, cname 174 CHARACTER(LEN=maxlen) :: str, fname, tname, pname, cname, ttype 199 175 INTEGER :: nsec, ierr, it, ntrac, ns, ip, ix, fType 200 176 INTEGER, ALLOCATABLE :: iGen(:) … … 232 208 CALL msg('This file is for air tracers only', modname, ns == 3 .AND. it == 1) 233 209 CALL msg('This files specifies the transporting fluid', modname, ns == 4 .AND. it == 1) 234 k => tracers(it) %keys210 k => tracers(it) 235 211 236 212 !=== NAME OF THE TRACER … … 238 214 ix = strIdx(oldHNO3, s(3)) 239 215 IF(ix /= 0 .AND. lRep) tname = newHNO3(ix) !--- Exception for HNO3 (REPROBUS ONLY) 240 tracers(it)%name = tname !--- Set the name of the tracer 241 CALL addKey('name', tname, k) !--- Set the name of the tracer 242 tracers(it)%keys%name = tname !--- Copy tracers names in keys components 216 CALL addKey('name', tname, tracers) !--- Set the name of the tracer 217 ! tracers(it)%name = tname !--- Copy tracers names in keys components 243 218 244 219 !=== NAME OF THE COMPONENT 245 220 cname = type_trac !--- Name of the model component 246 221 IF(ANY([(addPhase('H2O', ip), ip = 1, nphases)] == tname)) cname = 'lmdz' 247 tracers(it)%component = cname !--- Set component 248 CALL addKey('component', cname, k) !--- Set the name of the model component 222 CALL addKey('component', cname, tracers) !--- Set the name of the model component 249 223 250 224 !=== NAME OF THE PARENT … … 255 229 IF(ix /= 0 .AND. lRep) pname = newHNO3(ix) !--- Exception for HNO3 (REPROBUS ONLY) 256 230 END IF 257 tracers(it)%parent = pname !--- Set the parent name 258 CALL addKey('parent', pname, k) 231 CALL addKey('parent', pname, tracers) !--- Set the parent name 259 232 260 233 !=== PHASE AND ADVECTION SCHEMES NUMBERS 261 tracers(it)%phase = known_phases(ip:ip) !--- Set the phase of the tracer (default: "g"azeous) 262 CALL addKey('phase', known_phases(ip:ip), k) !--- Set the phase of the tracer (default: "g"azeous) 234 CALL addKey('phase', known_phases(ip:ip), tracers) !--- Set the phase of the tracer (default: "g"azeous) 263 235 CALL addKey('hadv', s(1), k) !--- Set the horizontal advection schemes number 264 236 CALL addKey('vadv', s(2), k) !--- Set the vertical advection schemes number … … 266 238 CLOSE(90) 267 239 lerr = setGeneration(tracers); IF(lerr) RETURN !--- Set iGeneration and gen0Name 268 lerr = getKey('iGeneration', iGen, tracers(:)%keys) !--- Generation number 269 WHERE(iGen == 2) tracers(:)%type = 'tag' !--- Set type: 'tracer' or 'tag' 240 lerr = getKey('iGeneration', iGen, tracers(:)) !--- Generation number 270 241 DO it = 1, ntrac 271 CALL addKey('type', tracers(it)%type, tracers(it)%keys) !--- Set the type of tracer 242 ttype = 'tracer'; IF(iGen(it) == 2) ttype = 'tag' 243 CALL addKey('type', ttype, tracers(it)) !--- Set the type of tracer 272 244 END DO 273 245 lerr = checkTracers(tracers, fname, fname); IF(lerr) RETURN !--- Detect orphans and check phases … … 291 263 END IF 292 264 lerr = indexUpdate(tracers); IF(lerr) RETURN !--- Set iqParent, iqDescen, nqDescen, nqChildren 293 IF(PRESENT(tracs)) CALL MOVE_ALLOC(FROM=tracers, TO=tracs)265 IF(PRESENT(tracs)) tracs = tracers 294 266 END FUNCTION readTracersFiles 295 267 !============================================================================================================================== … … 339 311 ! Purpose: Read the sections "snames(is)" (pipe-separated list) from each "fnames(is)" 340 312 ! file and create the corresponding tracers set descriptors in the database "dBase": 341 ! * dBase(id)%name 342 ! * dBase(id)%trac(:) %name : tracers names343 ! * dBase(id)%trac(it)%key s%key(:): names of keys associated to tracer dBase(id)%trac(it)%name344 ! * dBase(id)%trac(it)% keys%val(:): values of keys associated to tracer dBase(id)%trac(it)%name313 ! * dBase(id)%name : section name 314 ! * dBase(id)%trac(:) : tracers descriptor (the key "name" of tracers(i) is the name of the ith tracer) 315 ! * dBase(id)%trac(it)%key(:): names of keys associated to tracer dBase(id)%trac(it)%name 316 ! * dBase(id)%trac(it)%val(:): values of keys associated to tracer dBase(id)%trac(it)%name 345 317 !------------------------------------------------------------------------------------------------------------------------------ 346 318 CHARACTER(LEN=*), INTENT(IN) :: fnames(:) !--- Files names … … 395 367 ndb= SIZE(dBase) !--- Current number of sections in the database 396 368 IF(PRESENT(defName)) THEN !--- Add default values to all the tracers 397 DO idb=n0,ndb; CALL addDefault(dBase(idb)%trac, defName); END DO !--- and remove the virtual tracer "defName" 369 DO idb=n0,ndb !--- and remove the virtual tracer "defName" 370 lerr = addDefault(dBase(idb)%trac, defName); IF(lerr) RETURN 371 END DO 398 372 END IF 399 373 ll = strParse(snam, '|', keys = sec) !--- Requested sections names … … 408 382 !------------------------------------------------------------------------------------------------------------------------------ 409 383 CHARACTER(LEN=maxlen), ALLOCATABLE :: s(:), v(:) 410 TYPE(trac_type), ALLOCATABLE :: tt(:) 411 TYPE(trac_type) :: tmp 384 TYPE(keys_type), ALLOCATABLE :: tt(:) 412 385 CHARACTER(LEN=1024) :: str, str2 413 386 CHARACTER(LEN=maxlen) :: secn … … 445 418 tt = dBase(ndb)%trac(:) 446 419 v(1) = s(1); s(1) = 'name' !--- Convert "name" into a regular key 447 tmp%name = v(1); tmp%keys = keys_type(v(1), s(:), v(:)) !--- Set %name and %keys 448 dBase(ndb)%trac = [tt(:), tmp] 449 DEALLOCATE(tt, tmp%keys%key, tmp%keys%val) 420 dBase(ndb)%trac = [tt(:), keys_type(s(:), v(:))] 421 DEALLOCATE(tt) 450 422 END IF 451 423 END DO … … 460 432 461 433 !============================================================================================================================== 462 SUBROUTINE addDefault(t, defName)434 LOGICAL FUNCTION addDefault(t, defName) RESULT(lerr) 463 435 !------------------------------------------------------------------------------------------------------------------------------ 464 436 ! Purpose: Add the keys from virtual tracer named "defName" (if any) and remove this virtual tracer. 465 437 !------------------------------------------------------------------------------------------------------------------------------ 466 TYPE( trac_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: t(:)438 TYPE(keys_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: t(:) 467 439 CHARACTER(LEN=*), INTENT(IN) :: defName 468 440 INTEGER :: jd, it, k 469 TYPE(keys_type), POINTER :: ky 470 TYPE(trac_type), ALLOCATABLE :: tt(:) 471 jd = strIdx(t(:)%name, defName) 441 CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:) 442 TYPE(keys_type), ALLOCATABLE :: tt(:) 443 lerr = getKey('name', tname, t(:)); IF(lerr) RETURN 444 jd = strIdx(tname(:), defName) 472 445 IF(jd == 0) RETURN 473 ky => t(jd)%keys 474 DO k = 1, SIZE(ky%key) !--- Loop on the keys of the tracer named "defName" 475 ! CALL addKey(ky%key(k), ky%val(k), t(:)%keys, .FALSE.) !--- Add key to all the tracers (no overwriting) 476 DO it = 1, SIZE(t); CALL addKey(ky%key(k), ky%val(k), t(it)%keys, .FALSE.); END DO 446 DO k = 1, SIZE(t(jd)%key) !--- Loop on the keys of the tracer named "defName" 447 ! CALL addKey(t(jd)%key(k), t(jd)%val(k), t(:), .FALSE.) !--- Add key to all the tracers (no overwriting) 448 DO it = 1, SIZE(t); CALL addKey(t(jd)%key(k), t(jd)%val(k), t(it), .FALSE.); END DO 477 449 END DO 478 450 tt = [t(1:jd-1),t(jd+1:SIZE(t))]; CALL MOVE_ALLOC(FROM=tt, TO=t) !--- Remove the virtual tracer named "defName" 479 END SUBROUTINEaddDefault480 !============================================================================================================================== 481 482 !============================================================================================================================== 483 SUBROUTINE subDefault(t, defName, lSubLocal)451 END FUNCTION addDefault 452 !============================================================================================================================== 453 454 !============================================================================================================================== 455 LOGICAL FUNCTION subDefault(t, defName, lSubLocal) RESULT(lerr) 484 456 !------------------------------------------------------------------------------------------------------------------------------ 485 457 ! Purpose: Substitute the keys from virtual tracer named "defName" (if any) and remove this virtual tracer. 486 458 ! Substitute the keys locally (for the current tracer) if the flag "lSubLocal" is .TRUE. 487 459 !------------------------------------------------------------------------------------------------------------------------------ 488 TYPE( trac_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: t(:)460 TYPE(keys_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: t(:) 489 461 CHARACTER(LEN=*), INTENT(IN) :: defName 490 462 LOGICAL, INTENT(IN) :: lSubLocal 491 463 INTEGER :: i0, it, ik 492 TYPE(keys_type), POINTER :: k0, ky 493 TYPE(trac_type), ALLOCATABLE :: tt(:) 494 i0 = strIdx(t(:)%name, defName) 464 TYPE(keys_type), ALLOCATABLE :: tt(:) 465 CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:) 466 lerr = getKey('name', tname, t(:)); IF(lerr) RETURN 467 i0 = strIdx(tname(:), defName) 495 468 IF(i0 == 0) RETURN 496 k0 => t(i0)%keys497 469 DO it = 1, SIZE(t); IF(it == i0) CYCLE !--- Loop on the tracers 498 ky => t(it)%keys499 470 500 471 !--- Substitute in the values of <key>=<val> pairs the keys defined in the virtual tracer "defName" 501 DO ik = 1, SIZE( k0%key); CALL strReplace(ky%val, k0%key(ik), k0%val(ik), .TRUE.); END DO472 DO ik = 1, SIZE(t(i0)%key); CALL strReplace(t(it)%val, t(i0)%key(ik), t(i0)%val(ik), .TRUE.); END DO 502 473 503 474 IF(.NOT.lSubLocal) CYCLE 504 475 !--- Substitute in the values of <key>=<val> pairs the keys defined locally (in the current tracer) 505 DO ik = 1, SIZE( ky%key); CALL strReplace(ky%val, ky%key(ik), ky%val(ik), .TRUE.); END DO476 DO ik = 1, SIZE(t(it)%key); CALL strReplace(t(it)%val, t(it)%key(ik), t(it)%val(ik), .TRUE.); END DO 506 477 END DO 507 478 tt = [t(1:i0-1),t(i0+1:SIZE(t))]; CALL MOVE_ALLOC(FROM=tt, TO=t) !--- Remove the virtual tracer named "defName" 508 479 509 END SUBROUTINEsubDefault480 END FUNCTION subDefault 510 481 !============================================================================================================================== 511 482 … … 518 489 ! * Default values are provided for these keys because they are necessary. 519 490 !------------------------------------------------------------------------------------------------------------------------------ 520 TYPE( trac_type), ALLOCATABLE, INTENT(INOUT) :: tr(:) !--- Tracer derived type vector491 TYPE(keys_type), ALLOCATABLE, INTENT(INOUT) :: tr(:) !--- Tracer derived type vector 521 492 CHARACTER(LEN=*), INTENT(IN) :: sname !--- Current section name 522 493 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: fname !--- Tracers description file name 523 TYPE( trac_type), ALLOCATABLE :: ttr(:)494 TYPE(keys_type), ALLOCATABLE :: ttr(:) 524 495 CHARACTER(LEN=maxlen), ALLOCATABLE :: ta(:), pa(:), tname(:), parent(:), dType(:) 525 496 CHARACTER(LEN=maxlen) :: msg1, modname … … 529 500 lerr = .FALSE. 530 501 nt = SIZE(tr) 531 lerr = getKey('name', tname, tr(:) %keys); IF(lerr) RETURN532 lerr = getKey('parent', parent, tr(:) %keys, def = tran0); IF(lerr) RETURN533 lerr = getKey('type', dType, tr(:) %keys, def = 'tracer'); IF(lerr) RETURN502 lerr = getKey('name', tname, tr(:)); IF(lerr) RETURN 503 lerr = getKey('parent', parent, tr(:), def = tran0); IF(lerr) RETURN 504 lerr = getKey('type', dType, tr(:), def = 'tracer'); IF(lerr) RETURN 534 505 nq = 0 535 506 !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ … … 537 508 !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 538 509 !--- Extract useful keys: parent name, type, component name 539 tr(it)%component = sname 540 CALL addKey('component', sname, tr(it)%keys) 510 CALL addKey('component', sname, tr(it)) 541 511 542 512 !--- Determine the number of tracers and parents ; coherence checking … … 565 535 DO ipr = 1, npr !--- Loop on parents list elts 566 536 DO itr = 1, ntr !--- Loop on tracers list elts 567 ttr(iq)%keys%name = TRIM(ta(itr)) 568 ttr(iq)%keys%key = tr(it)%keys%key 569 ttr(iq)%keys%val = tr(it)%keys%val 570 ttr(iq)%name = TRIM(ta(itr)) 571 ttr(iq)%parent = TRIM(pa(ipr)) 572 ttr(iq)%type = dType(it) 573 ttr(iq)%component = sname 574 CALL addKey('name', ta(itr), ttr(iq)%keys) 575 CALL addKey('parent', pa(ipr), ttr(iq)%keys) 576 CALL addKey('type', dType(it), ttr(iq)%keys) 577 CALL addKey('component', sname, ttr(iq)%keys) 537 ttr(iq)%key = tr(it)%key 538 ttr(iq)%val = tr(it)%val 539 CALL addKey('name', ta(itr), ttr(iq)) 540 CALL addKey('parent', pa(ipr), ttr(iq)) 541 CALL addKey('type', dType(it), ttr(iq)) 542 CALL addKey('component', sname, ttr(iq)) 578 543 iq = iq + 1 579 544 END DO … … 597 562 ! Check also for orphan tracers (tracers without parent). 598 563 !------------------------------------------------------------------------------------------------------------------------------ 599 TYPE( trac_type), INTENT(INOUT) :: tr(:) !--- Tracer derived type vector564 TYPE(keys_type), INTENT(INOUT) :: tr(:) !--- Tracer derived type vector 600 565 INTEGER :: iq, jq, ig 601 566 CHARACTER(LEN=maxlen), ALLOCATABLE :: parent(:), tname(:) … … 603 568 CHARACTER(LEN=maxlen) :: modname 604 569 modname = 'setGeneration' 605 lerr = getKey('name', tname, ky=tr(:) %keys); IF(lerr) RETURN606 lerr = getKey('parent', parent, ky=tr(:) %keys); IF(lerr) RETURN570 lerr = getKey('name', tname, ky=tr(:)); IF(lerr) RETURN 571 lerr = getKey('parent', parent, ky=tr(:)); IF(lerr) RETURN 607 572 DO iq = 1, SIZE(tr) 608 573 jq = iq; ig = 0 … … 613 578 ig = ig + 1 614 579 END DO 615 tr(iq)%gen0Name = tname(jq) 616 tr(iq)%iGeneration = ig 617 CALL addKey('iGeneration', ig, tr(iq)%keys) 618 CALL addKey('gen0Name', tname(jq), tr(iq)%keys) 580 CALL addKey('iGeneration', ig, tr(iq)) 581 CALL addKey('gen0Name', tname(jq), tr(iq)) 619 582 END DO 620 583 END FUNCTION setGeneration … … 629 592 ! * check wether the phases are known or not (elements of "known_phases") 630 593 !------------------------------------------------------------------------------------------------------------------------------ 631 TYPE( trac_type), INTENT(IN) :: tr(:) !--- Tracer derived typevector594 TYPE(keys_type), INTENT(IN) :: tr(:) !--- Tracers description vector 632 595 CHARACTER(LEN=*), INTENT(IN) :: sname !--- Section name 633 596 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: fname !--- File name … … 644 607 mesg = 'Check section "'//TRIM(sname)//'"' 645 608 IF(PRESENT(fname)) mesg=TRIM(mesg)//' in file "'//TRIM(fname)//'"' 646 lerr = getKey('iGeneration', iGen, tr(:) %keys);IF(lerr) RETURN647 lerr = getKey('name', tname, tr(:) %keys);IF(lerr) RETURN609 lerr = getKey('iGeneration', iGen, tr(:)); IF(lerr) RETURN 610 lerr = getKey('name', tname, tr(:)); IF(lerr) RETURN 648 611 649 612 !=== CHECK FOR ORPHAN TRACERS … … 652 615 !=== CHECK PHASES 653 616 DO iq = 1, nq; IF(iGen(iq) /= 0) CYCLE !--- Generation O only is checked 654 IF(getKey(['phases','phase '], pha, iq, tr(:) %keys, lDisp=.FALSE.)) pha = 'g' !--- Phase617 IF(getKey(['phases','phase '], pha, iq, tr(:), lDisp=.FALSE.)) pha = 'g' !--- Phase 655 618 np = LEN_TRIM(pha); bp(iq)=' ' 656 619 DO ip = 1, np; p = pha(ip:ip); IF(INDEX(known_phases, p) == 0) bp(iq) = TRIM(bp(iq))//p; END DO … … 667 630 ! Purpose: Make sure that tracers are not repeated. 668 631 !------------------------------------------------------------------------------------------------------------------------------ 669 TYPE( trac_type), INTENT(IN) :: tr(:) !--- Tracer derived typevector632 TYPE(keys_type), INTENT(IN) :: tr(:) !--- Tracers description vector 670 633 CHARACTER(LEN=*), INTENT(IN) :: sname !--- Section name 671 634 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: fname !--- File name … … 684 647 nq=SIZE(tr,DIM=1); lerr=.FALSE. !--- Number of lines ; error flag 685 648 tdup(:) = '' 686 lerr = getKey('name', tname, tr %keys); IF(lerr) RETURN687 lerr = getKey('type', dType, tr %keys); IF(lerr) RETURN688 lerr = getKey('iGeneration', iGen, tr %keys); IF(lerr) RETURN649 lerr = getKey('name', tname, tr); IF(lerr) RETURN 650 lerr = getKey('type', dType, tr); IF(lerr) RETURN 651 lerr = getKey('iGeneration', iGen, tr); IF(lerr) RETURN 689 652 DO iq = 1, nq 690 653 IF(dType(iq) == 'tag') CYCLE !--- Tags can be repeated … … 698 661 DO k = 1, nq 699 662 IF(.NOT.ll(k)) CYCLE !--- Skip tracers different from current one 700 IF(getKey(['phases','phase '], phase, k, tr %keys, lDisp=.FALSE.)) phase='g'!--- Get current phases663 IF(getKey(['phases','phase '], phase, k, tr, lDisp=.FALSE.)) phase='g'!--- Get current phases 701 664 IF(INDEX(phase, p) /= 0) np = np + 1 !--- One more appearance of current tracer with phase "p" 702 665 END DO … … 718 681 ! Purpose: Expand the phases in the tracers descriptor "tr". Phases are not repeated for a tracer, thanks to "checkUnique". 719 682 !------------------------------------------------------------------------------------------------------------------------------ 720 TYPE( trac_type), ALLOCATABLE, INTENT(INOUT) :: tr(:) !--- Tracer derived typevector721 !------------------------------------------------------------------------------------------------------------------------------ 722 TYPE( trac_type), ALLOCATABLE :: ttr(:)683 TYPE(keys_type), ALLOCATABLE, INTENT(INOUT) :: tr(:) !--- Tracers description vector 684 !------------------------------------------------------------------------------------------------------------------------------ 685 TYPE(keys_type), ALLOCATABLE :: ttr(:) 723 686 INTEGER, ALLOCATABLE :: i0(:), iGen(:) 724 687 CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:), gen0N(:), phase(:), parents(:), dType(:) … … 732 695 nq = SIZE(tr, DIM=1) 733 696 nt = 0 734 lerr = getKey('name', tname, tr %keys); IF(lerr) RETURN!--- Names of the tracers735 lerr = getKey('gen0Name', gen0N, tr %keys); IF(lerr) RETURN!--- Names of the tracers of first generation736 lerr = getKey('iGeneration', iGen, tr %keys); IF(lerr) RETURN!--- Generation number737 lerr = getKey('phases', phase, tr %keys); IF(lerr) RETURN!--- Phases names738 lerr = getKey('parent', parents, tr %keys); IF(lerr) RETURN!--- Parents names739 lerr = getKey('type', dType, tr %keys); IF(lerr) RETURN!--- Tracers types ('tracer' or 'tag')697 lerr = getKey('name', tname, tr); IF(lerr) RETURN !--- Names of the tracers 698 lerr = getKey('gen0Name', gen0N, tr); IF(lerr) RETURN !--- Names of the tracers of first generation 699 lerr = getKey('iGeneration', iGen, tr); IF(lerr) RETURN !--- Generation number 700 lerr = getKey('phases', phase, tr); IF(lerr) RETURN !--- Phases names 701 lerr = getKey('parent', parents, tr); IF(lerr) RETURN !--- Parents names 702 lerr = getKey('type', dType, tr); IF(lerr) RETURN !--- Tracers types ('tracer' or 'tag') 740 703 DO iq = 1, nq !--- GET THE NUMBER OF TRACERS 741 704 IF(iGen(iq) /= 0) CYCLE !--- Only deal with generation 0 tracers … … 763 726 IF(lTag) nam = TRIM(nam)//'_'//TRIM(tname(iq)) !--- <parent>_<name> for tags 764 727 ttr(it) = tr(iq) !--- Same <key>=<val> pairs 765 ttr(it)%name = TRIM(nam) !--- Name with possibly phase suffix 766 ttr(it)%keys%name = TRIM(nam) !--- Name inside the keys decriptor 767 ttr(it)%phase = p !--- Single phase entry 768 CALL addKey('name', nam, ttr(it)%keys) 769 CALL addKey('phase', p, ttr(it)%keys) 728 CALL addKey('name', nam, ttr(it)) !--- Name with possibly phase suffix 729 CALL addKey('phase', p, ttr(it)) !--- Single phase entry 770 730 IF(lExt) THEN 771 731 parent = parents(iq); IF(iGen(iq) > 0) parent = addPhase(parent, p) 772 732 gen0Nm = gen0N(iq); IF(iGen(iq) > 0) gen0Nm = addPhase(gen0Nm, p) 773 ttr(it)%parent = parent 774 ttr(it)%gen0Name = gen0Nm 775 CALL addKey('parent', parent, ttr(it)%keys) 776 CALL addKey('gen0Name', gen0Nm, ttr(it)%keys) 733 CALL addKey('parent', parent, ttr(it)) 734 CALL addKey('gen0Name', gen0Nm, ttr(it)) 777 735 END IF 778 736 it = it+1 … … 782 740 END DO 783 741 CALL MOVE_ALLOC(FROM=ttr, TO=tr) 784 CALL delKey(['phases'], tr) !--- Remove few keys entries742 CALL delKey(['phases'], tr) !--- Remove "phases" key, useless since "phase" is defined 785 743 786 744 END FUNCTION expandPhases … … 797 755 ! TO BE ADDED IF NECESSARY: HIGHER MOMENTS AT THE END 798 756 !------------------------------------------------------------------------------------------------------------------------------ 799 TYPE(trac_type), INTENT(INOUT) :: tr(:) !--- Tracer derived type vector 800 !------------------------------------------------------------------------------------------------------------------------------ 801 TYPE(trac_type), ALLOCATABLE :: tr2(:) 802 INTEGER, ALLOCATABLE :: iy(:), iz(:) 803 INTEGER, ALLOCATABLE :: iGen(:) 757 TYPE(keys_type), INTENT(INOUT) :: tr(:) !--- Tracers description vector 758 !------------------------------------------------------------------------------------------------------------------------------ 759 TYPE(keys_type), ALLOCATABLE :: tr2(:) 760 INTEGER, ALLOCATABLE :: iy(:), iz(:), iGen(:) 804 761 CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:), gen0N(:) 805 762 INTEGER :: ig, ng, iq, jq, ip, nq, n, ix(SIZE(tr)), k … … 807 764 ! tr2 is introduced in order to cope with a bug in gfortran 4.8.5 compiler 808 765 !------------------------------------------------------------------------------------------------------------------------------ 809 lerr = getKey('iGeneration', iGen, tr %keys); IF(lerr) RETURN!--- Generation number766 lerr = getKey('iGeneration', iGen, tr); IF(lerr) RETURN !--- Generation number 810 767 nq = SIZE(tr) 811 768 DO ip = nphases, 1, -1 812 lerr = getKey('name', tname, tr %keys); IF(lerr) RETURN!--- Names of the tracers of first generation769 lerr = getKey('name', tname, tr); IF(lerr) RETURN !--- Names of the tracers of first generation 813 770 iq = strIdx(tname, addPhase('H2O', ip)) 814 771 IF(iq == 0) CYCLE … … 826 783 END DO 827 784 ELSE 828 lerr = getKey('gen0Name', gen0N, tr%keys); IF(lerr) RETURN!--- Names of the tracers iq = 1785 lerr = getKey('gen0Name', gen0N, tr); IF(lerr) RETURN !--- Names of the tracers iq = 1 829 786 DO jq = 1, nq !--- Loop on generation 0 tracers 830 787 IF(iGen(jq) /= 0) CYCLE !--- Skip generations /= 0 … … 848 805 LOGICAL FUNCTION mergeTracers(sections, tr) RESULT(lerr) 849 806 TYPE(dataBase_type), TARGET, INTENT(IN) :: sections(:) 850 TYPE(trac_type), ALLOCATABLE, INTENT(OUT) :: tr(:) 851 TYPE(trac_type), POINTER :: t1(:), t2(:) 852 TYPE(keys_type), POINTER :: k1(:), k2(:) 807 TYPE(keys_type), ALLOCATABLE, INTENT(OUT) :: tr(:) 808 TYPE(keys_type), POINTER :: t1(:), t2(:) 853 809 INTEGER, ALLOCATABLE :: ixct(:), ixck(:) 854 810 INTEGER :: is, ik, ik1, ik2, nk2, i1, i2, nt2 … … 858 814 lerr = .FALSE. 859 815 keys = ['parent ', 'type ', 'iGeneration'] !--- Mandatory keys 860 t1 => sections(1)%trac(:) ; k1 => t1(:)%keys !--- Alias: first tracers section, corresponding keys861 lerr = getKey('name', n1, k1); IF(lerr) RETURN !--- Names of the tracers816 t1 => sections(1)%trac(:) !--- Alias: first tracers section 817 lerr = getKey('name', n1, t1); IF(lerr) RETURN !--- Names of the tracers 862 818 tr = t1 863 819 !---------------------------------------------------------------------------------------------------------------------------- … … 865 821 !---------------------------------------------------------------------------------------------------------------------------- 866 822 t2 => sections(is)%trac(:) !--- Alias: current tracers section 867 k2 => t2(:)%keys 868 lerr = getKey('name', n2, k2); IF(lerr) RETURN !--- Names of the tracers 823 lerr = getKey('name', n2, t2); IF(lerr) RETURN !--- Names of the tracers 869 824 nt2 = SIZE(t2(:), DIM=1) !--- Number of tracers in section 870 825 ixct = strIdx(n1(:), n2(:)) !--- Indexes of common tracers … … 874 829 CALL msg(n1(PACK(ixct, MASK = ixct/=0)), modname, nmax=128) !--- Display duplicates (the 128 first at most) 875 830 !-------------------------------------------------------------------------------------------------------------------------- 876 DO i2=1,nt2; tnam = TRIM( t2(i2)%name)!=== LOOP ON COMMON TRACERS831 DO i2=1,nt2; tnam = TRIM(n2(i2)) !=== LOOP ON COMMON TRACERS 877 832 !-------------------------------------------------------------------------------------------------------------------------- 878 833 i1 = ixct(i2); IF(i1 == 0) CYCLE !--- Idx in t1(:) ; skip new tracers … … 881 836 s1=' of "'//TRIM(tnam)//'" in "'//TRIM(sections(is)%name)//'" not matching previous value' 882 837 DO ik = 1, SIZE(keys) 883 lerr = getKey(keys(ik), v1, i1, k1)884 lerr = getKey(keys(ik), v2, i2, k2)838 lerr = getKey(keys(ik), v1, i1, t1) 839 lerr = getKey(keys(ik), v2, i2, t2) 885 840 lerr = v1 /= v2; IF(fmsg(TRIM(keys(ik))//TRIM(s1), modname, lerr)) RETURN 886 841 END DO 887 842 888 !=== GET THE INDICES IN tr(i2)%key s%key(:) OF THE KEYS ALSO PRESENT IN tr(i1)%keys%key(:)889 nk2 = SIZE( k2(i2)%key(:)) !--- Keys number in current section890 ixck = strIdx( k1(i1)%key(:), k2(i2)%key(:)) !--- Common keys indexes891 !--- APPEND THE NEW KEYS PAIRS IN tr(i1)%key s%key(:)892 tr(i1)%key s%key = [ tr(i1)%keys%key, PACK(tr(i2)%keys%key, MASK = ixck==0)]893 tr(i1)% keys%val = [ tr(i1)%keys%val, PACK(tr(i2)%keys%val, MASK = ixck==0)]843 !=== GET THE INDICES IN tr(i2)%key(:) OF THE KEYS ALSO PRESENT IN tr(i1)%key(:) 844 nk2 = SIZE(t2(i2)%key(:)) !--- Keys number in current section 845 ixck = strIdx(t1(i1)%key(:), t2(i2)%key(:)) !--- Common keys indexes 846 !--- APPEND THE NEW KEYS PAIRS IN tr(i1)%key(:) 847 tr(i1)%key = [ tr(i1)%key, PACK(tr(i2)%key, MASK = ixck==0)] 848 tr(i1)%val = [ tr(i1)%val, PACK(tr(i2)%val, MASK = ixck==0)] 894 849 895 850 !=== KEEP TRACK OF THE COMPONENTS NAMES: COMA-SEPARATED LIST 896 lerr = getKey('component', v1, i1, k1) 897 lerr = getKey('component', v2, i2, k2) 898 tr(i1)%component = TRIM(v1)//','//TRIM(v2) 899 CALL addKey('component', TRIM(v1)//','//TRIM(v2), tr(i1)%keys) 851 lerr = getKey('component', v1, i1, t1) 852 lerr = getKey('component', v2, i2, t2) 853 CALL addKey('component', TRIM(v1)//','//TRIM(v2), tr(i1)) 900 854 901 855 !=== FOR TRACERS COMMON TO PREVIOUS AND CURRENT SECTIONS: CHECK WETHER SOME KEYS HAVE DIFFERENT VALUES ; KEEP OLD ONE 902 856 DO ik2 = 1, nk2 !--- Collect the corresponding indices 903 857 ik1 = ixck(ik2); IF(ik1 == 0) CYCLE 904 IF( k1(i1)%val(ik1) == k2(i2)%val(ik2)) ixck(ik2)=0858 IF(t1(i1)%val(ik1) == t2(i2)%val(ik2)) ixck(ik2)=0 905 859 END DO 906 860 IF(ALL(ixck==0)) CYCLE !--- No identical keys with /=values => nothing to display 907 861 CALL msg('Key(s)'//TRIM(s1), modname) !--- Display the keys with /=values (names list) 908 862 DO ik2 = 1, nk2 !--- Loop on keys found in both t1(:) and t2(:) 909 knam = k2(i2)%key(ik2) !--- Name of the current key863 knam = t2(i2)%key(ik2) !--- Name of the current key 910 864 ik1 = ixck(ik2) !--- Corresponding index in t1(:) 911 865 IF(ik1 == 0) CYCLE !--- New keys are skipped 912 v1 = k1(i1)%val(ik1); v2 = k2(i2)%val(ik2) !--- Key values in t1(:) and t2(:)866 v1 = t1(i1)%val(ik1); v2 = t2(i2)%val(ik2) !--- Key values in t1(:) and t2(:) 913 867 CALL msg(' * '//TRIM(knam)//'='//TRIM(v2)//' ; previous value kept:'//TRIM(v1), modname) 914 868 END DO … … 925 879 LOGICAL FUNCTION cumulTracers(sections, tr, lRename) RESULT(lerr) 926 880 TYPE(dataBase_type), TARGET, INTENT(IN) :: sections(:) 927 TYPE( trac_type), ALLOCATABLE, INTENT(OUT) :: tr(:)881 TYPE(keys_type), ALLOCATABLE, INTENT(OUT) :: tr(:) 928 882 LOGICAL, OPTIONAL, INTENT(IN) :: lRename !--- .TRUE.: add a section suffix to identical names 929 883 CHARACTER(LEN=maxlen) :: tnam_new, modname … … 934 888 tr = [( sections(is)%trac(:), is = 1, SIZE(sections) )] !--- Concatenated tracers vector 935 889 IF(PRESENT(lRename)) THEN; IF(lRename) RETURN; END IF !--- No renaming: finished 936 lerr = getKey('name', tname, tr %keys); IF(lerr) RETURN!--- Names937 lerr = getKey('parent', parent, tr %keys); IF(lerr) RETURN!--- Parents938 lerr = getKey('component', comp, tr %keys); IF(lerr) RETURN!--- Component name890 lerr = getKey('name', tname, tr); IF(lerr) RETURN !--- Names 891 lerr = getKey('parent', parent, tr); IF(lerr) RETURN !--- Parents 892 lerr = getKey('component', comp, tr); IF(lerr) RETURN !--- Component name 939 893 !---------------------------------------------------------------------------------------------------------------------------- 940 894 DO iq = 1, SIZE(tr); IF(COUNT(tname == tname(iq)) == 1) CYCLE !=== LOOP ON TRACERS 941 895 !---------------------------------------------------------------------------------------------------------------------------- 942 896 tnam_new = TRIM(tname(iq))//'_'//TRIM(comp(iq)) !--- Same with section extension 943 CALL addKey('name', tnam_new, tr(iq)%keys) !--- Modify tracer name 944 tr(iq)%name = TRIM(tnam_new) !--- Modify tracer name 897 CALL addKey('name', tnam_new, tr(iq)) !--- Modify tracer name 945 898 !-------------------------------------------------------------------------------------------------------------------------- 946 899 DO jq = 1, SIZE(tr); IF(parent(jq) /= tname(iq)) CYCLE !=== LOOP ON TRACERS PARENTS 947 900 !-------------------------------------------------------------------------------------------------------------------------- 948 CALL addKey('parent', tnam_new, tr(jq)%keys) !--- Modify tracer name 949 tr(jq)%parent = TRIM(tnam_new) !--- Modify tracer name 901 CALL addKey('parent', tnam_new, tr(jq)) !--- Modify tracer name 950 902 !-------------------------------------------------------------------------------------------------------------------------- 951 903 END DO … … 994 946 tmp = int2str([(iq, iq=1, nq)]) 995 947 ELSE 996 lerr = getKey(nam, tmp, dBase(idb)%trac(:) %keys, lDisp=lMandatory)948 lerr = getKey(nam, tmp, dBase(idb)%trac(:), lDisp=lMandatory) 997 949 END IF 998 950 IF(lerr) THEN; lerr = lMandatory; RETURN; END IF … … 1013 965 LOGICAL FUNCTION aliasTracer(tname, trac, alias) RESULT(lerr) !=== TRACER NAMED "tname" - SCALAR 1014 966 CHARACTER(LEN=*), INTENT(IN) :: tname 1015 TYPE( trac_type), TARGET, INTENT(IN) :: trac(:)1016 TYPE( trac_type), POINTER, INTENT(OUT) :: alias967 TYPE(keys_type), TARGET, INTENT(IN) :: trac(:) 968 TYPE(keys_type), POINTER, INTENT(OUT) :: alias 1017 969 INTEGER :: it 1018 970 CHARACTER(LEN=maxlen), ALLOCATABLE :: tnames(:) 1019 971 alias => NULL() 1020 lerr = getKey('name', tnames, trac(:) %keys)972 lerr = getKey('name', tnames, trac(:)) 1021 973 it = strIdx(tnames, tname) 1022 974 lerr = it /= 0; IF(.NOT.lerr) alias => trac(it) … … 1024 976 !============================================================================================================================== 1025 977 LOGICAL FUNCTION trSubset_Indx(trac, idx, alias) RESULT(lerr) !=== TRACERS WITH INDICES "idx(:)" - VECTOR 1026 TYPE( trac_type), ALLOCATABLE, INTENT(IN) :: trac(:)978 TYPE(keys_type), ALLOCATABLE, INTENT(IN) :: trac(:) 1027 979 INTEGER, INTENT(IN) :: idx(:) 1028 TYPE( trac_type), ALLOCATABLE, INTENT(OUT) :: alias(:)980 TYPE(keys_type), ALLOCATABLE, INTENT(OUT) :: alias(:) 1029 981 alias = trac(idx) 1030 982 lerr = indexUpdate(alias) … … 1032 984 !------------------------------------------------------------------------------------------------------------------------------ 1033 985 LOGICAL FUNCTION trSubset_Name(trac, tname, alias) RESULT(lerr) !=== TRACERS NAMED "tname(:)" - VECTOR 1034 TYPE( trac_type), ALLOCATABLE, INTENT(IN) :: trac(:)986 TYPE(keys_type), ALLOCATABLE, INTENT(IN) :: trac(:) 1035 987 CHARACTER(LEN=*), INTENT(IN) :: tname(:) 1036 TYPE( trac_type), ALLOCATABLE, INTENT(OUT) :: alias(:)988 TYPE(keys_type), ALLOCATABLE, INTENT(OUT) :: alias(:) 1037 989 CHARACTER(LEN=maxlen), ALLOCATABLE :: tnames(:) 1038 lerr = getKey('name', tnames, trac(:) %keys)990 lerr = getKey('name', tnames, trac(:)) 1039 991 alias = trac(strIdx(tnames, tname)) 1040 992 lerr = indexUpdate(alias) … … 1042 994 !============================================================================================================================== 1043 995 LOGICAL FUNCTION trSubset_gen0Name(trac, gen0Nm, alias) RESULT(lerr) !=== TRACERS OF COMMON 1st GENERATION ANCESTOR 1044 TYPE( trac_type), ALLOCATABLE, INTENT(IN) :: trac(:)996 TYPE(keys_type), ALLOCATABLE, INTENT(IN) :: trac(:) 1045 997 CHARACTER(LEN=*), INTENT(IN) :: gen0Nm 1046 TYPE( trac_type), ALLOCATABLE, INTENT(OUT) :: alias(:)998 TYPE(keys_type), ALLOCATABLE, INTENT(OUT) :: alias(:) 1047 999 CHARACTER(LEN=maxlen), ALLOCATABLE :: gen0N(:) 1048 lerr = getKey('gen0Name', gen0N, trac(:) %keys)1000 lerr = getKey('gen0Name', gen0N, trac(:)) 1049 1001 alias = trac(strFind(delPhase(gen0N), gen0Nm)) 1050 1002 lerr = indexUpdate(alias) … … 1054 1006 1055 1007 !============================================================================================================================== 1056 !=== UPDATE THE INDEXES iqParent, iqDescen d AND iGeneration IN THE TRACERS DESCRIPTOR LIST "tr" (USEFULL FOR SUBSETS)=========1008 !=== UPDATE THE INDEXES iqParent, iqDescen, nqDescen, nqChildren IN THE TRACERS DESCRIPTOR LIST "tr" ========================== 1057 1009 !============================================================================================================================== 1058 1010 LOGICAL FUNCTION indexUpdate(tr) RESULT(lerr) 1059 TYPE( trac_type), INTENT(INOUT) :: tr(:)1011 TYPE(keys_type), INTENT(INOUT) :: tr(:) 1060 1012 INTEGER :: iq, jq, nq, ig, nGen 1061 1013 INTEGER, ALLOCATABLE :: iqDescen(:), ix(:), iy(:) 1062 1014 CHARACTER(LEN=maxlen), ALLOCATABLE :: tnames(:), parent(:) 1063 1015 INTEGER, DIMENSION(SIZE(tr)) :: iqParent, iGen 1064 lerr = getKey('name', tnames, tr %keys); IF(lerr) RETURN!--- Names1065 lerr = getKey('parent', parent, tr %keys); IF(lerr) RETURN!--- Parents1016 lerr = getKey('name', tnames, tr); IF(lerr) RETURN !--- Names 1017 lerr = getKey('parent', parent, tr); IF(lerr) RETURN !--- Parents 1066 1018 nq = SIZE(tr) 1067 1019 1068 !=== iqParent , iGeneration1020 !=== iqParent 1069 1021 DO iq = 1, nq; iGen(iq) = 0; jq = iq 1070 1022 iqParent(iq) = strIdx(tnames, parent(iq)) 1071 1023 DO; jq = strIdx(tnames, parent(jq)); IF(jq == 0) EXIT; iGen(iq) = iGen(iq) + 1; END DO 1072 CALL addKey('iqParent', parent(iq), tr(iq)%keys) 1073 CALL addKey('iqGeneration', iGen(iq), tr(iq)%keys) 1024 CALL addKey('iqParent', iqParent(iq), tr(iq)) 1074 1025 END DO 1075 1026 … … 1078 1029 DO iq = 1, nq 1079 1030 ix = [iq]; ALLOCATE(iqDescen(0)) 1031 CALL addKey('nqChildren', 0, tr(iq)) 1080 1032 DO ig = iGen(iq)+1, nGen 1081 1033 iy = find(iqParent, ix); iqDescen = [iqDescen, iy]; ix = iy 1082 1034 IF(ig /= iGen(iq)+1) CYCLE 1083 CALL addKey('nqChildren', SIZE(iqDescen), tr(iq)%keys) 1084 tr(iq)%nqChildren = SIZE(iqDescen) 1035 CALL addKey('nqChildren', SIZE(iqDescen), tr(iq)) 1085 1036 END DO 1086 CALL addKey('iqDescen', strStack(int2str(iqDescen)), tr(iq)%keys) 1087 CALL addKey('nqDescen', SIZE(iqDescen), tr(iq)%keys) 1088 tr(iq)%iqDescen = iqDescen 1089 tr(iq)%nqDescen = SIZE(iqDescen) 1037 CALL addKey('iqDescen', strStack(int2str(iqDescen)), tr(iq)) 1038 CALL addKey('nqDescen', SIZE(iqDescen), tr(iq)) 1090 1039 DEALLOCATE(iqDescen) 1091 1040 END DO … … 1095 1044 1096 1045 !============================================================================================================================== 1097 !=== READ FILE "fnam" TO APPEND THE "dBase" TRACERS DATABASE WITH AS MUCH SECTIONS AS PARENTS NAMES IN "isot(:)%parent":====1098 !=== * Each section dBase(i)%name contains the isotopes "dBase(i)%trac(:)" descending on "dBase(i)%name"="iso(i)% parent"====1046 !=== READ FILE "fnam" TO APPEND THE "dBase" TRACERS DATABASE WITH AS MUCH SECTIONS AS ISOTOPES CLASSES IN "isot(:)%name": ==== 1047 !=== * Each section dBase(i)%name contains the isotopes "dBase(i)%trac(:)" descending on "dBase(i)%name"="iso(i)%name" ==== 1099 1048 !=== * For each isotopes class, the <key>=<val> vector of each tracer is moved into the isotopes descriptor "isot" ==== 1100 1049 !=== NOTES: ==== 1101 1050 !=== * Most of the "isot" components have been defined in the calling routine (processIsotopes): ==== 1102 !=== parent, nzone, zone(:), niso, keys(:)%name, ntiso, trac(:), nphas, phas, iqIsoPha(:,:), itZonPhi(:,:)====1051 !=== name, nzone, zone(:), niso, keys(:)%name, ntiso, trac(:), nphas, phas, iqIsoPha(:,:), itZonPhi(:,:) ==== 1103 1052 !=== * Same syntax for isotopes file and "tracer.def": a tracers section contains one line for each of its isotopes ==== 1104 1053 !=== * Each tracers section can contain a "params" virtual isotope line of isotopes parameters default values ==== … … 1109 1058 LOGICAL FUNCTION readIsotopesFile(fnam, isot) RESULT(lerr) 1110 1059 CHARACTER(LEN=*), INTENT(IN) :: fnam !--- Input file name 1111 TYPE(isot_type), TARGET, INTENT(INOUT) :: isot(:) !--- Isotopes descriptors (field % parentmust be defined!)1060 TYPE(isot_type), TARGET, INTENT(INOUT) :: isot(:) !--- Isotopes descriptors (field %name must be defined!) 1112 1061 LOGICAL :: lFound 1113 1062 INTEGER :: is, iis, it, idb, ndb, nb0 1114 CHARACTER(LEN=maxlen), ALLOCATABLE :: vals(:) 1063 CHARACTER(LEN=maxlen), ALLOCATABLE :: vals(:), tname(:), iname(:) 1115 1064 CHARACTER(LEN=maxlen) :: modname 1116 TYPE( trac_type), POINTER :: tt(:),t1065 TYPE(keys_type), POINTER :: t 1117 1066 TYPE(dataBase_type), ALLOCATABLE :: tdb(:) 1118 1067 modname = 'readIsotopesFile' 1119 1068 1120 1069 !--- THE INPUT FILE MUST BE PRESENT 1121 INQUIRE(FILE=TRIM(fnam), EXIST=lFound); lerr = .NOT.lFound 1122 IF(fmsg('Missing isotopes parameters file "'//TRIM(fnam)//'"', modname, lerr)) RETURN 1123 1124 !--- READ THE FILE SECTIONS, ONE EACH PARENT TRACER 1070 INQUIRE(FILE=TRIM(fnam), EXIST=lFound) 1071 lerr = .NOT.lFound 1072 CALL msg('Missing isotopes parameters file "'//TRIM(fnam)//'"', modname, lerr) 1073 IF(lerr) RETURN 1074 1075 !--- READ THE FILE SECTIONS, ONE EACH ISOTOPES CLASS (FIEDL %name) 1125 1076 nb0 = SIZE(dBase, DIM=1)+1 !--- Next database element index 1126 lerr = readSections(fnam,strStack(isot(:)% parent,'|')); IF(lerr) RETURN !--- Read sections, one each parent tracer1077 lerr = readSections(fnam,strStack(isot(:)%name,'|')); IF(lerr) RETURN !--- Read sections, one each isotopes class %name 1127 1078 ndb = SIZE(dBase, DIM=1) !--- Current database size 1128 1079 DO idb = nb0, ndb … … 1130 1081 1131 1082 !--- GET FEW GLOBAL KEYS FROM "def" FILES AND ADD THEM TO THE 'params' SECTION 1132 CALL addKeysFromDef(dBase(idb)%trac, 'params') 1083 ! lerr = addKeysFromDef(dBase(idb)%trac, 'params'); IF(lerr) RETURN 1133 1084 1134 1085 !--- SUBSTITUTE THE KEYS DEFINED IN THE 'params' VIRTUAL TRACER ; SUBSTITUTE LOCAL KEYS ; REMOVE 'params' VIRTUAL TRACER 1135 CALL subDefault(dBase(idb)%trac, 'params', .TRUE.) 1136 1137 tt => dBase(idb)%trac 1086 lerr = subDefault(dBase(idb)%trac, 'params', .TRUE.); IF(lerr) RETURN 1138 1087 1139 1088 !--- REDUCE THE EXPRESSIONS TO OBTAIN SCALARS AND TRANSFER THEM TO THE "isot" ISOTOPES DESCRIPTORS VECTOR 1089 lerr = getKey('name', tname, dBase(idb)%trac); IF(lerr) RETURN 1090 lerr = getKey('name', iname, isot(iis)%keys); IF(lerr) RETURN 1140 1091 DO it = 1, SIZE(dBase(idb)%trac) 1141 1092 t => dBase(idb)%trac(it) 1142 is = strIdx(i sot(iis)%keys(:)%name, t%name) !--- Index in "isot(iis)%keys(:)%name" of isotope "t%name"1093 is = strIdx(iname, tname(it)) !--- Index in "iname(:)" of isotope "tname(it)" 1143 1094 IF(is == 0) CYCLE 1144 lerr = ANY(reduceExpr(t% keys%val, vals)); IF(lerr) RETURN!--- Reduce expressions ; detect non-numerical elements1145 isot(iis)%keys(is)%key = t%key s%key1095 lerr = ANY(reduceExpr(t%val, vals)); IF(lerr) RETURN !--- Reduce expressions ; detect non-numerical elements 1096 isot(iis)%keys(is)%key = t%key 1146 1097 isot(iis)%keys(is)%val = vals 1147 1098 END DO 1148 1099 1149 1100 !--- CHECK FOR MISSING ISOTOPES (NO KEYS ALLOCATED) 1150 lerr = checkList(i sot(iis)%keys(:)%name, .NOT.[( ALLOCATED(isot(iis)%keys(is)%key), is=1, SIZE(isot(iis)%keys) )], &1101 lerr = checkList(iname, .NOT.[( ALLOCATED(isot(iis)%keys(is)%key), is=1, SIZE(isot(iis)%keys) )], & 1151 1102 'Check file "'//TRIM(fnam)//'" in section "'//TRIM(dBase(idb)%name)//'"', 'isotopes', 'missing') 1152 1103 IF(lerr) RETURN … … 1161 1112 1162 1113 !--- GET THE isoCheck ENTRY FROM THE *.DEF FILES (MIGHT BE CHANGED TO A CLASS-DEPENDANT KEYWORD) 1163 CALL get_in('ok_iso_verif', isot(strIdx(i sot%parent, 'H2O'))%check, .FALSE.)1114 CALL get_in('ok_iso_verif', isot(strIdx(iname, 'H2O'))%check, .FALSE.) 1164 1115 1165 1116 lerr = dispIsotopes() … … 1171 1122 INTEGER :: ik, nk, ip, it, nt 1172 1123 CHARACTER(LEN=maxlen) :: prf 1173 CHARACTER(LEN=maxlen), ALLOCATABLE :: ttl(:), val(:,:) 1124 CHARACTER(LEN=maxlen), ALLOCATABLE :: ttl(:), val(:,:), tname(:) 1174 1125 CALL msg('Isotopes parameters read from file "'//TRIM(fnam)//'":', modname) 1175 DO ip = 1, SIZE(isot) !--- Loop on parents tracers 1126 DO ip = 1, SIZE(isot) !--- Loop on isotopes classes 1127 IF(SIZE(isot(ip)%keys) == 0) CYCLE 1176 1128 nk = SIZE(isot(ip)%keys(1)%key) !--- Same keys for each isotope 1177 1129 nt = SIZE(isot(ip)%keys) !--- Number of isotopes … … 1179 1131 ALLOCATE(ttl(nk+2), val(nt,nk+1)) 1180 1132 ttl(1:2) = ['it ','name']; ttl(3:nk+2) = isot(ip)%keys(1)%key(:)!--- Titles line with keys names 1181 val(:,1) = isot(ip)%keys(:)%name !--- Values table 1st column: isotopes names 1133 lerr = getKey('name', tname, isot(ip)%keys); IF(lerr) RETURN 1134 val(:,1) = tname !--- Values table 1st column: isotopes names 1182 1135 DO ik = 1, nk 1183 1136 DO it = 1, nt … … 1199 1152 !=== IF ISOTOPES (2ND GENERATION TRACERS) ARE DETECTED: === 1200 1153 !=== * COMPUTE MOST OF THE RELATED QUANTITIES ("isot" COMPONENTS). === 1201 !=== * COMPUTE FEW ISOTOPES-DEDICATED "trac" COMPONENTS === 1202 !=== * CALL readIsotopesFile TO GET PHYSICAL QUANTITIES (<key>=<val> PAIRS) === 1203 !=== NOTE: THIS IS DONE HERE (IN A ROUTINE CALLED BY THE DYNAMIC), BECAUSE THE DYNAMIC NEEDS FEW PHYSICAL PARAMETERS. === 1204 !============================================================================================================================== 1205 LOGICAL FUNCTION processIsotopes(iNames) RESULT(lerr) 1206 CHARACTER(LEN=maxlen), TARGET, OPTIONAL, INTENT(IN) :: iNames(:) 1207 CHARACTER(LEN=maxlen), ALLOCATABLE :: p(:), str(:) !--- Temporary storage 1208 CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:), parent(:), dType(:), phase(:), gen0N(:) 1209 CHARACTER(LEN=maxlen) :: iName, modname 1210 CHARACTER(LEN=1) :: ph !--- Phase 1211 INTEGER, ALLOCATABLE :: iGen(:) 1212 INTEGER :: ic, ip, iq, it, iz 1213 LOGICAL, ALLOCATABLE :: ll(:) !--- Mask 1214 TYPE(trac_type), POINTER :: t(:), t1 1215 TYPE(isot_type), POINTER :: i 1154 !=== * COMPUTE FEW ISOTOPES-DEDICATED "trac" COMPONENTS (defined by "keys(:)") === 1155 !=== * CALL readIsotopesFile TO GET PHYSICAL QUANTITIES (<key>=<val> PAIRS) /!\ DISABLED FUNCTION /!\ === 1156 !============================================================================================================================== 1157 LOGICAL FUNCTION processIsotopes(keys, isot, iClasses) RESULT(lerr) 1158 TYPE(keys_type), TARGET, OPTIONAL, INTENT(INOUT) :: keys(:) 1159 TYPE(isot_type), TARGET, ALLOCATABLE, OPTIONAL, INTENT(OUT) :: isot(:) 1160 CHARACTER(LEN=*), TARGET, OPTIONAL, INTENT(IN) :: iClasses(:) 1161 CHARACTER(LEN=maxlen), ALLOCATABLE :: p(:), str1(:), str2(:) !--- Temporary storage 1162 CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:), parent(:), dType(:), phase(:), gen0N(:), iCla(:) 1163 CHARACTER(LEN=maxlen) :: iClass, modname 1164 CHARACTER(LEN=1) :: ph !--- Phase 1165 LOGICAL, ALLOCATABLE :: ll(:) !--- Mask 1166 INTEGER, ALLOCATABLE :: iGen(:) 1167 INTEGER :: ic, ip, iq, ii, it, iz 1168 TYPE(isot_type), POINTER :: i1 1169 TYPE(keys_type), POINTER :: k(:) 1216 1170 1217 1171 lerr = .FALSE. 1218 1172 modname = 'readIsotopesFile' 1219 1220 t => tracers 1221 1222 lerr = getKey('name', tname, t%keys); IF(lerr) RETURN !--- Names 1223 lerr = getKey('parent', parent, t%keys); IF(lerr) RETURN !--- Parents 1224 lerr = getKey('type', dType, t%keys); IF(lerr) RETURN !--- Tracer type 1225 lerr = getKey('phase', phase, t%keys); IF(lerr) RETURN !--- Phase 1226 lerr = getKey('gen0Name', gen0N, t%keys); IF(lerr) RETURN !--- 1st generation ancestor name 1227 lerr = getKey('iGeneration', iGen, t%keys); IF(lerr) RETURN !--- Generation number 1173 k => tracers; IF(PRESENT(keys )) k => keys 1174 lerr = getKey('name', tname, k); IF(lerr) RETURN !--- Names 1175 lerr = getKey('parent', parent, k); IF(lerr) RETURN !--- Parents 1176 lerr = getKey('type', dType, k); IF(lerr) RETURN !--- Tracer type 1177 lerr = getKey('phase', phase, k); IF(lerr) RETURN !--- Phase 1178 lerr = getKey('gen0Name', gen0N, k); IF(lerr) RETURN !--- 1st generation ancestor name 1179 lerr = getKey('iGeneration', iGen, k); IF(lerr) RETURN !--- Generation number 1180 1181 !--- INITIALIZATION IF ISOTOPES-SPECIFIC KEYS (MUST BE DEFINED EVEN WITHOUT ISOTOPES) 1182 DO iq = 1, SIZE(k) 1183 CALL addKey('iso_iGroup',0, k(iq)) !--- Family idx in list "isotopes(:)%parent" 1184 CALL addKey('iso_iName', 0, k(iq)) !--- Isotope idx in effective isotopes list 1185 CALL addKey('iso_iZone', 0, k(iq)) !--- Tagging zone idx in effective zones list 1186 CALL addKey('iso_iPhas', 0, k(iq)) !--- Phase idx in effective phases list 1187 END DO 1228 1188 1229 1189 !--- GET FROM "tracers" THE FULL LIST OF AVAILABLE ISOTOPES CLASSES 1230 p= PACK(delPhase(parent), MASK = dType=='tracer' .AND. iGen==1)1231 CALL strReduce( p, nbIso)1232 1233 !--- CHECK WHETHER NEEDED ISOTOPES CLASSES "i Names" ARE AVAILABLE OR NOT1234 IF(PRESENT(i Names)) THEN1235 DO it = 1, SIZE(i Names)1236 lerr = ALL( p /= iNames(it))1237 IF(fmsg('No isotopes class "'//TRIM(i Names(it))//'" found among tracers', modname, lerr)) RETURN1190 iCla = PACK(delPhase(parent), MASK = dType=='tracer' .AND. iGen==1) 1191 CALL strReduce(iCla) 1192 1193 !--- CHECK WHETHER NEEDED ISOTOPES CLASSES "iClasses" ARE AVAILABLE OR NOT 1194 IF(PRESENT(iClasses)) THEN 1195 DO it = 1, SIZE(iClasses) 1196 lerr = ALL(iCla /= iClasses(it)) 1197 IF(fmsg('No isotopes class "'//TRIM(iClasses(it))//'" found among tracers', modname, lerr)) RETURN 1238 1198 END DO 1239 p = iNames; nbIso = SIZE(p)1199 iCla = iClasses 1240 1200 END IF 1241 IF(ALLOCATED(isotopes)) DEALLOCATE(isotopes) 1242 ALLOCATE(isotopes(nbIso)) 1243 1201 nbIso = SIZE(iCla) 1202 1203 !--- USE THE ARGUMENT "isot" TO STORE THE ISOTOPIC DATABASE OR THE LOCAL VECTOR "isotopes" 1204 IF(PRESENT(isot)) THEN 1205 ALLOCATE( isot(nbIso)) 1206 ELSE 1207 IF(ALLOCATED(isotopes)) DEALLOCATE(isotopes) 1208 ALLOCATE(isotopes(nbIso)) 1209 END IF 1244 1210 IF(nbIso==0) RETURN !=== NO ISOTOPES: FINISHED 1245 1211 1246 1212 !--- ISOTOPES RELATED VARIABLES ; NULL OR EMPTY IF NO ISOTOPES 1247 isotopes(:)%parent = p 1248 DO ic = 1, SIZE(p) !--- Loop on isotopes classes 1249 i => isotopes(ic) 1250 iname = i%parent !--- Current isotopes class name (parent tracer name) 1251 1252 !=== Isotopes children of tracer "iname": mask, names, number (same for each phase of "iname") 1253 ll = dType=='tracer' .AND. delPhase(parent) == iname .AND. phase == 'g' 1254 str = PACK(delPhase(tname), MASK = ll) !--- Effectively found isotopes of "iname" 1255 i%niso = SIZE(str) !--- Number of "effectively found isotopes of "iname" 1256 ALLOCATE(i%keys(i%niso)) 1257 FORALL(it = 1:i%niso) i%keys(it)%name = str(it) 1258 1259 !=== Geographic tagging tracers descending on tracer "iname": mask, names, number 1260 ll = dType=='tag' .AND. delPhase(gen0N) == iname .AND. iGen == 2 1261 i%zone = PACK(strTail(tname,'_',.TRUE.), MASK = ll) !--- Tagging zones names for isotopes category "iname" 1262 CALL strReduce(i%zone) 1263 i%nzone = SIZE(i%zone) !--- Tagging zones number for isotopes category "iname" 1264 1265 !=== Geographic tracers of the isotopes children of tracer "iname" (same for each phase of "iname") 1213 DO ic = 1, nbIso !--- Loop on isotopes classes 1214 IF( PRESENT(isot)) i1 => isot (ic) 1215 IF(.NOT.PRESENT(isot)) i1 => isotopes(ic) 1216 iClass = iCla(ic) !--- Current isotopes class name (parent tracer name) 1217 i1%name = iClass 1218 1219 !=== Isotopes children of tracer "iClass": mask, names, number (same for each phase of "iClass") 1220 ll = dType=='tracer' .AND. delPhase(parent) == iClass .AND. phase == 'g' 1221 str1 = PACK(delPhase(tname), MASK = ll) !--- Effectively found isotopes of "iClass" 1222 i1%niso = SIZE(str1) !--- Number of "effectively found isotopes of "iname" 1223 ALLOCATE(i1%keys(i1%niso)) 1224 DO it = 1, i1%niso; CALL addKey('name', str1(it), i1%keys(it)); END DO 1225 1226 !=== Geographic tagging tracers descending on tracer "iClass": mask, names, number 1227 ll = dType=='tag' .AND. delPhase(gen0N) == iClass .AND. iGen == 2 1228 i1%zone = PACK(strTail(tname, '_', .TRUE.), MASK = ll) !--- Tagging zones names for isotopes category "iname" 1229 CALL strReduce(i1%zone) 1230 i1%nzone = SIZE(i1%zone) !--- Tagging zones number for isotopes category "iClass" 1231 1232 !=== Geographic tracers of the isotopes children of tracer "iClass" (same for each phase of "iClass") 1266 1233 ! NOTE: One might like to create a similar variable for 2nd generation tagging tracers (tagging the gen1 tracers) 1267 str = PACK(delPhase(tname), MASK=ll)1268 CALL strReduce(str )1269 i %ntiso = i%niso + SIZE(str)!--- Number of isotopes + their geographic tracers [ntiso]1270 ALLOCATE(i %trac(i%ntiso))1271 FORALL(it = 1:i%niso) i%trac(it) = i%keys(it)%name1272 FORALL(it = i%niso+1:i%ntiso) i%trac(it) = str(it-i%niso)1273 1274 !=== Phases for tracer "i name"1275 i %phase = ''1276 DO ip = 1, nphases; ph = known_phases(ip:ip); IF( strIdx(t%name,addPhase(iname, ph)) /= 0) i%phase = TRIM(i%phase)//ph; END DO1277 i %nphas = LEN_TRIM(i%phase) !--- Equal to "nqo" for water1234 str2 = PACK(delPhase(tname), MASK=ll) 1235 CALL strReduce(str2) 1236 i1%ntiso = i1%niso + SIZE(str2) !--- Number of isotopes + their geographic tracers [ntiso] 1237 ALLOCATE(i1%trac(i1%ntiso)) 1238 DO it = 1, i1%niso; i1%trac(it) = str1(it); END DO 1239 DO it = i1%niso+1, i1%ntiso; i1%trac(it) = str2(it-i1%niso); END DO 1240 1241 !=== Phases for tracer "iClass" 1242 i1%phase = '' 1243 DO ip = 1, nphases; ph = known_phases(ip:ip); IF(ANY(tname == addPhase(iClass, ph))) i1%phase = TRIM(i1%phase)//ph; END DO 1244 i1%nphas = LEN_TRIM(i1%phase) !--- Equal to "nqo" for water 1278 1245 1279 1246 !=== Tables giving the index in a table of effectively found items for each dynamical tracer (1<=iq<=nqtot) 1280 DO iq = 1, SIZE(t) 1281 t1 => tracers(iq) 1282 IF(delPhase(t1%gen0Name)/=iname .OR. t1%iGeneration==0) CYCLE !--- Only deal with tracers descending on "iname" 1283 t1%iso_iGroup = ic !--- Isotopes family idx in list "isotopes(:)%parent" 1284 t1%iso_iName = strIdx(i%trac, strHead(delPhase(t1%name),'_',.TRUE.)) !--- Current isotope idx in effective isotopes list 1285 t1%iso_iZone = strIdx(i%zone, strTail(t1%name, '_',.TRUE.)) !--- Current isotope zone idx in effective zones list 1286 t1%iso_iPhase = INDEX(i%phase,TRIM(t1%phase)) !--- Current isotope phase idx in effective phases list 1287 IF(t1%iGeneration /= 2) t1%iso_iZone = 0 !--- Skip possible generation 1 tagging tracers 1247 DO iq = 1, SIZE(tracers) 1248 ii = strIdx(i1%trac, strHead(delPhase(tname(iq)), '_', .TRUE.)) 1249 iz = strIdx(i1%zone, strTail( tname(iq), '_', .TRUE.)) 1250 ip = INDEX(i1%phase, TRIM(phase(iq) )) 1251 IF(delPhase(gen0N(iq)) /= iClass .OR. iGen(iq) == 0) CYCLE !--- Only deal with tracers descending on "iClass" 1252 CALL addKey('iso_iGroup',ic, k(iq)) !--- Family idx in list "isotopes(:)%name" 1253 CALL addKey('iso_iName', ii, k(iq)) !--- Isotope idx in effective isotopes list 1254 CALL addKey('iso_iZone', iz, k(iq)) !--- Tagging zone idx in effective zones list 1255 CALL addKey('iso_iPhas', ip, k(iq)) !--- Phase idx in effective phases list 1256 IF(iGen(iq) /= 2) CALL addKey('iso_iZone', 0, k(iq)) !--- Skip possible generation 1 tagging tracers 1288 1257 END DO 1289 1258 1290 1259 !=== Table used to get iq (index in dyn array, size nqtot) from the isotope and phase indexes ; the full isotopes list 1291 1260 ! (including tagging tracers) is sorted this way: iso1, iso2, ..., iso1_zone1, iso2_zone1, ..., iso1_zoneN, iso2_zoneN 1292 i %iqIsoPha = RESHAPE( [( (strIdx(t%name, addPhase(i%trac(it),i%phase(ip:ip))), it=1, i%ntiso), ip=1, i%nphas)], &1293 [i %ntiso, i%nphas] )1261 i1%iqIsoPha = RESHAPE( [( (strIdx(tname, addPhase(i1%trac(it),i1%phase(ip:ip))), it=1, i1%ntiso), ip=1, i1%nphas)], & 1262 [i1%ntiso, i1%nphas] ) 1294 1263 !=== Table used to get iq (index in dyn array, size nqtot) from the water and isotope and phase indexes ; the full isotopes list 1295 1264 ! (including tagging tracers) is sorted this way: iso1, iso2, ..., iso1_zone1, iso2_zone1, ..., iso1_zoneN, iso2_zoneN 1296 i %iqWIsoPha = RESHAPE( [( [strIdx(t%name, addPhase('H2O',i%phase(ip:ip))), i%iqIsoPha(:,ip)], ip=1,i%nphas)], &1297 [1+i %ntiso, i%nphas] )1265 i1%iqWIsoPha = RESHAPE( [( [strIdx(tname, addPhase('H2O', i1%phase(ip:ip))), i1%iqIsoPha(:,ip)], ip=1, i1%nphas)], & 1266 [1+i1%ntiso, i1%nphas] ) 1298 1267 !=== Table used to get ix (index in tagging tracers isotopes list, size ntiso) from the zone and isotope indexes 1299 i %itZonIso = RESHAPE( [( (strIdx(i%trac(:), TRIM(i%trac(it))//'_'//TRIM(i%zone(iz))), iz=1, i%nzone), it=1, i%niso )], &1300 [i %nzone, i%niso] )1268 i1%itZonIso = RESHAPE( [( (strIdx(i1%trac(:), TRIM(i1%trac(it))//'_'//TRIM(i1%zone(iz))), iz=1, i1%nzone), it=1, i1%niso )], & 1269 [i1%nzone, i1%niso] ) 1301 1270 END DO 1302 1271 1303 !=== READ PHYSICAL PARAMETERS FROM isoFile FILE 1304 ! lerr = readIsotopesFile(isoFile, isotopes); IF(lerr) RETURN! on commente pour ne pas chercher isotopes_params.def 1272 !=== READ PHYSICAL PARAMETERS FROM isoFile FILE (COMMENTED => DISABLED) 1273 ! IF( PRESENT(isot)) lerr = readIsotopesFile(isoFile, isot) 1274 ! IF(.NOT.PRESENT(isot)) lerr = readIsotopesFile(isoFile, isotopes) 1275 ! IF(lerr) RETURN 1305 1276 1306 1277 !--- GET THE isoCheck ENTRY FROM THE *.DEF FILES (MIGHT BE CHANGED TO A CLASS-DEPENDANT KEYWORD) … … 1311 1282 1312 1283 !=== SELECT WATER ISOTOPES CLASS OR, IF UNFOUND, THE FIRST ISOTOPES CLASS 1313 IF(isoSelect('H2O', .TRUE.)) THEN; iH2O = ixIso; ELSE; lerr = isoSelect(1, .TRUE.); END IF 1284 IF(isoSelect('H2O', lVerbose=.TRUE.)) THEN 1285 iH2O = ixIso 1286 ELSE 1287 lerr = isoSelect(1, lVerbose=.TRUE.) 1288 END IF 1314 1289 1315 1290 CONTAINS … … 1319 1294 !------------------------------------------------------------------------------------------------------------------------------ 1320 1295 INTEGER :: ix, it, ip, np, iz, nz, npha, nzon 1321 TYPE(isot_type), POINTER :: i1322 1296 DO ix = 1, nbIso 1323 i => isotopes(ix) 1297 IF( PRESENT(isot)) i1 => isot (ix) 1298 IF(.NOT.PRESENT(isot)) i1 => isotopes(ix) 1324 1299 !--- Check whether each isotope and tagging isotopic tracer is present in the same number of phases 1325 DO it = 1, i %ntiso; npha = i%nphas1326 np = SUM([(COUNT(t racers(:)%name == addPhase(i%trac(it), i%phase(ip:ip))), ip=1, npha)])1300 DO it = 1, i1%ntiso; npha = i1%nphas 1301 np = SUM([(COUNT(tname(:) == addPhase(i1%trac(it), i1%phase(ip:ip))), ip=1, npha)]) 1327 1302 lerr = np /= npha 1328 CALL msg(TRIM(int2str(np))// ' phases instead of '//TRIM(int2str(npha))//' for '//TRIM(i%trac(it)), modname, lerr)1303 CALL msg(TRIM(int2str(np))// ' phases instead of '//TRIM(int2str(npha))//' for '//TRIM(i1%trac(it)), modname, lerr) 1329 1304 IF(lerr) RETURN 1330 1305 END DO 1331 DO it = 1, i %niso; nzon = i%nzone1332 nz = SUM([(COUNT(i %trac == TRIM(i%trac(it))//'_'//i%zone(iz)), iz=1, nzon)])1306 DO it = 1, i1%niso; nzon = i1%nzone 1307 nz = SUM([(COUNT(i1%trac == TRIM(i1%trac(it))//'_'//i1%zone(iz)), iz=1, nzon)]) 1333 1308 lerr = nz /= nzon 1334 CALL msg(TRIM(int2str(nz))//' tagging zones instead of '//TRIM(int2str(nzon))//' for '//TRIM(i %trac(it)), modname, lerr)1309 CALL msg(TRIM(int2str(nz))//' tagging zones instead of '//TRIM(int2str(nzon))//' for '//TRIM(i1%trac(it)), modname, lerr) 1335 1310 IF(lerr) RETURN 1336 1311 END DO … … 1345 1320 !============================================================================================================================== 1346 1321 !=== THE ROUTINE isoSelect IS USED TO SWITCH FROM AN ISOTOPE FAMILY TO ANOTHER: ISOTOPES DEPENDENT PARAMETERS ARE UPDATED 1347 ! Single generic "isoSelect" routine, using the predefined index of the parent(fast version) or its name (first call).1348 !============================================================================================================================== 1349 LOGICAL FUNCTION isoSelectByName(i Name, lVerbose) RESULT(lerr)1322 ! Single generic "isoSelect" routine, using the predefined index of the class (fast version) or its name (first call). 1323 !============================================================================================================================== 1324 LOGICAL FUNCTION isoSelectByName(iClass, isot, lVerbose) RESULT(lerr) 1350 1325 IMPLICIT NONE 1351 CHARACTER(LEN=*), INTENT(IN) :: iName 1352 LOGICAL, OPTIONAL, INTENT(IN) :: lVerbose 1326 CHARACTER(LEN=*), INTENT(IN) :: iClass 1327 TYPE(isot_type), OPTIONAL, TARGET, INTENT(IN) :: isot(:) 1328 LOGICAL, OPTIONAL, INTENT(IN) :: lVerbose 1329 TYPE(isot_type), POINTER :: iso(:) 1353 1330 INTEGER :: iIso 1354 1331 LOGICAL :: lV 1355 lV = .FALSE.; IF(PRESENT(lVerbose)) lV = lVerbose 1356 iIso = strIdx(isotopes(:)%parent, iName) 1332 lV = .FALSE.; IF(PRESENT(lVerbose)) lV = lVerbose 1333 iso => isotopes; IF(PRESENT(isot)) iso => isot 1334 iIso = strIdx(iso(:)%name, iClass) 1357 1335 lerr = iIso == 0 1358 1336 IF(lerr) THEN 1359 1337 niso = 0; ntiso = 0; nzone = 0; nphas = 0; isoCheck=.FALSE. 1360 CALL msg('no isotope family named "'//TRIM(i Name)//'"', ll=lV)1338 CALL msg('no isotope family named "'//TRIM(iClass)//'"', ll=lV) 1361 1339 RETURN 1362 1340 END IF 1363 lerr = isoSelectByIndex(iIso, lV)1341 lerr = isoSelectByIndex(iIso, iso, lV) 1364 1342 END FUNCTION isoSelectByName 1365 1343 !============================================================================================================================== 1366 LOGICAL FUNCTION isoSelectByIndex(iIso, lVerbose) RESULT(lerr)1344 LOGICAL FUNCTION isoSelectByIndex(iIso, isot, lVerbose) RESULT(lerr) 1367 1345 IMPLICIT NONE 1368 INTEGER, INTENT(IN) :: iIso 1369 LOGICAL, OPTIONAL, INTENT(IN) :: lVerbose 1346 INTEGER, INTENT(IN) :: iIso 1347 TYPE(isot_type), TARGET, OPTIONAL, INTENT(INOUT) :: isot(:) 1348 LOGICAL, OPTIONAL, INTENT(IN) :: lVerbose 1349 TYPE(isot_type), POINTER :: i(:) 1370 1350 LOGICAL :: lV 1371 lv = .FALSE.; IF(PRESENT(lVerbose)) lv = lVerbose 1351 lV = .FALSE.; IF(PRESENT(lVerbose)) lV = lVerbose 1352 i => isotopes; IF(PRESENT(isot)) i => isot 1372 1353 lerr = .FALSE. 1373 1354 IF(iIso == ixIso) RETURN !--- Nothing to do if the index is already OK 1374 lerr = iIso<=0 .OR. iIso>SIZE(i sotopes)1355 lerr = iIso<=0 .OR. iIso>SIZE(i) 1375 1356 CALL msg('Inconsistent isotopes family index '//TRIM(int2str(iIso))//': should be > 0 and <= '& 1376 //TRIM(int2str(SIZE(i sotopes)))//'"', ll = lerr .AND. lV)1357 //TRIM(int2str(SIZE(i)))//'"', ll = lerr .AND. lV) 1377 1358 IF(lerr) RETURN 1378 1359 ixIso = iIso !--- Update currently selected family index 1379 isotope => i sotopes(ixIso)!--- Select corresponding component1360 isotope => i(ixIso) !--- Select corresponding component 1380 1361 isoKeys => isotope%keys; niso = isotope%niso 1381 1362 isoName => isotope%trac; ntiso = isotope%ntiso … … 1384 1365 itZonIso => isotope%itZonIso; isoCheck = isotope%check 1385 1366 iqIsoPha => isotope%iqIsoPha 1386 iqWIsoPha 1367 iqWIsoPha=> isotope%iqWIsoPha 1387 1368 END FUNCTION isoSelectByIndex 1388 1369 !============================================================================================================================== … … 1528 1509 !=== OVERWRITE THE KEYS OF THE TRACER NAMED "tr0" WITH THE VALUES FOUND IN THE *.def FILES, IF ANY. =========================== 1529 1510 !============================================================================================================================== 1530 SUBROUTINE addKeysFromDef(t, tr0)1531 TYPE( trac_type), ALLOCATABLE, INTENT(INOUT) :: t(:)1511 LOGICAL FUNCTION addKeysFromDef(t, tr0) RESULT(lerr) 1512 TYPE(keys_type), ALLOCATABLE, INTENT(INOUT) :: t(:) 1532 1513 CHARACTER(LEN=*), INTENT(IN) :: tr0 1533 1514 !------------------------------------------------------------------------------------------------------------------------------ 1515 CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:) 1534 1516 CHARACTER(LEN=maxlen) :: val 1535 1517 INTEGER :: ik, jd 1536 jd = strIdx(t%name, tr0) 1518 lerr = getKey('name', tname, t); IF(lerr) RETURN 1519 jd = strIdx(tname(:), tr0) 1537 1520 IF(jd == 0) RETURN 1538 DO ik = 1, SIZE(t(jd)%key s%key)1539 CALL get_in(t(jd)%key s%key(ik), val, '*none*')1540 IF(val /= '*none*') CALL addKey(t(jd)%key s%key(ik), val, t(jd)%keys, .TRUE.)1521 DO ik = 1, SIZE(t(jd)%key) 1522 CALL get_in(t(jd)%key(ik), val, '*none*') 1523 IF(val /= '*none*') CALL addKey(t(jd)%key(ik), val, t(jd), .TRUE.) 1541 1524 END DO 1542 END SUBROUTINEaddKeysFromDef1525 END FUNCTION addKeysFromDef 1543 1526 !============================================================================================================================== 1544 1527 … … 1550 1533 INTEGER, INTENT(IN) :: itr 1551 1534 CHARACTER(LEN=*), INTENT(IN) :: keyn(:) 1552 TYPE( trac_type), INTENT(INOUT) :: ky(:)1535 TYPE(keys_type), INTENT(INOUT) :: ky(:) 1553 1536 !------------------------------------------------------------------------------------------------------------------------------ 1554 1537 CHARACTER(LEN=maxlen), ALLOCATABLE :: k(:), v(:) … … 1556 1539 INTEGER :: iky 1557 1540 IF(itr<=0 .OR. itr>SIZE(ky, DIM=1)) RETURN !--- Index is out of range 1558 ll = [( ALL(keyn/=ky(itr)%key s%key(iky)), iky=1, SIZE(ky(itr)%keys%key) )]1559 k = PACK(ky(itr)%key s%key, MASK=ll); CALL MOVE_ALLOC(FROM=k, TO=ky(itr)%keys%key)1560 v = PACK(ky(itr)% keys%val, MASK=ll); CALL MOVE_ALLOC(FROM=v, TO=ky(itr)%keys%val)1541 ll = [( ALL(keyn/=ky(itr)%key(iky)), iky=1, SIZE(ky(itr)%key) )] 1542 k = PACK(ky(itr)%key, MASK=ll); CALL MOVE_ALLOC(FROM=k, TO=ky(itr)%key) 1543 v = PACK(ky(itr)%val, MASK=ll); CALL MOVE_ALLOC(FROM=v, TO=ky(itr)%val) 1561 1544 END SUBROUTINE delKey_1 1562 1545 !============================================================================================================================== 1563 1546 SUBROUTINE delKey(keyn, ky) 1564 1547 CHARACTER(LEN=*), INTENT(IN) :: keyn(:) 1565 TYPE( trac_type), INTENT(INOUT) :: ky(:)1548 TYPE(keys_type), INTENT(INOUT) :: ky(:) 1566 1549 !------------------------------------------------------------------------------------------------------------------------------ 1567 1550 INTEGER :: iky … … 1611 1594 !=== TRY TO GET THE KEY NAMED "key" FOR THE "itr"th TRACER IN: === 1612 1595 !=== * ARGUMENT "ky" DATABASE IF SPECIFIED ; OTHERWISE: === 1613 !=== * IN INTERNAL TRACERS DATABASE "tracers(:) %keys" (IF UNFOUND, IN INTERNAL ISOTOPES DATABASE "isotope%keys(:)")===1596 !=== * IN INTERNAL TRACERS DATABASE "tracers(:)" (IF UNFOUND, IN INTERNAL ISOTOPES DATABASE "isotope%keys(:)") === 1614 1597 !=== THE RETURNED VALUE (STRING, AN INTEGER, A REAL OR A LOGICAL) CAN BE EITHER: === 1615 1598 !=== * A SCALAR === … … 1677 1660 lerr = .TRUE. 1678 1661 IF(lerr .AND. PRESENT(ky)) val = fgetKey(ky) !--- "ky" 1679 IF(lerr .AND. ALLOCATED (tracers)) val = fgetKey(tracers(:) %keys)!--- "tracers"1662 IF(lerr .AND. ALLOCATED (tracers)) val = fgetKey(tracers(:)) !--- "tracers" 1680 1663 IF(lerr .AND. ASSOCIATED(isotope)) val = fgetKey(isotope%keys(:)) !--- "isotope" 1681 1664 IF(lerr .AND. PRESENT(def)) THEN … … 1782 1765 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 1783 1766 val = str2int(svals) 1784 lerr = ANY(val == -HUGE(1)) 1767 lerr = ANY(val == -HUGE(1)) .AND. sval /= '' 1785 1768 s = 'key "'//TRIM(keyn)//'" of tracer nr. '//TRIM(int2str(itr))//' is not' 1786 1769 CALL msg(TRIM(s)//' an integer: '//TRIM(sval), modname, lerr) … … 1802 1785 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 1803 1786 val = str2real(svals) 1804 lerr = ANY(val == -HUGE(1.)) 1787 lerr = ANY(val == -HUGE(1.)) .AND. sval /= '' 1805 1788 s = 'key "'//TRIM(keyn)//'" of tracer nr. '//TRIM(int2str(itr))//' is not' 1806 1789 CALL msg(TRIM(s)//' a real: '//TRIM(sval), modname, lerr) … … 1823 1806 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 1824 1807 ivals = str2bool(svals) 1825 lerr = ANY(ivals == -1) 1808 lerr = ANY(ivals == -1) .AND. sval /= '' 1826 1809 s = 'key "'//TRIM(keyn)//'" of tracer nr. '//TRIM(int2str(itr))//' is not' 1827 1810 CALL msg(TRIM(s)//' a boolean: '//TRIM(sval), modname, lerr) … … 1860 1843 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 1861 1844 val = str2int(svals) 1862 lerr = ANY(val == -HUGE(1)) 1845 lerr = ANY(val == -HUGE(1)) .AND. sval /= '' 1863 1846 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of tracer nr. '//TRIM(int2str(itr))//' is not' 1864 1847 CALL msg(TRIM(s)//' an integer: '//TRIM(sval), modname, lerr) … … 1881 1864 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 1882 1865 val = str2real(svals) 1883 lerr = ANY(val == -HUGE(1.)) 1866 lerr = ANY(val == -HUGE(1.)) .AND. sval /= '' 1884 1867 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of tracer nr. '//TRIM(int2str(itr))//' is not' 1885 1868 CALL msg(TRIM(s)//' a real: '//TRIM(sval), modname, lerr) … … 1903 1886 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 1904 1887 ivals = str2bool(svals) 1905 lerr = ANY(ivals == -1) 1888 lerr = ANY(ivals == -1) .AND. sval /= '' 1906 1889 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of tracer nr. '//TRIM(int2str(itr))//' is not' 1907 1890 CALL msg(TRIM(s)//' a boolean: '//TRIM(sval), modname, lerr) … … 1910 1893 !============================================================================================================================== 1911 1894 !============================================================================================================================== 1912 LOGICAL FUNCTION getKeyByIndex_s1mm(keyn, val, ky, nam, def, lDisp) RESULT(lerr) 1913 CHARACTER(LEN=*), INTENT(IN) :: keyn 1914 CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) :: val(:) 1915 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1916 CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: nam(:) 1917 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: def 1918 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1919 lerr = getKeyByIndex_smmm([keyn], val, ky, nam, def, lDisp) 1895 LOGICAL FUNCTION getKeyByIndex_s1mm(keyn, val, ky, def, lDisp) RESULT(lerr) 1896 CHARACTER(LEN=*), INTENT(IN) :: keyn 1897 CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) :: val(:) 1898 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1899 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: def 1900 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1901 lerr = getKeyByIndex_smmm([keyn], val, ky, def, lDisp) 1920 1902 END FUNCTION getKeyByIndex_s1mm 1921 1903 !============================================================================================================================== 1922 LOGICAL FUNCTION getKeyByIndex_i1mm(keyn, val, ky, nam, def, lDisp) RESULT(lerr) 1923 CHARACTER(LEN=*), INTENT(IN) :: keyn 1924 INTEGER, ALLOCATABLE, INTENT(OUT) :: val(:) 1925 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1926 CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: nam(:) 1927 INTEGER, OPTIONAL, INTENT(IN) :: def 1928 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1929 lerr = getKeyByIndex_immm([keyn], val, ky, nam, def, lDisp) 1904 LOGICAL FUNCTION getKeyByIndex_i1mm(keyn, val, ky, def, lDisp) RESULT(lerr) 1905 CHARACTER(LEN=*), INTENT(IN) :: keyn 1906 INTEGER, ALLOCATABLE, INTENT(OUT) :: val(:) 1907 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1908 INTEGER, OPTIONAL, INTENT(IN) :: def 1909 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1910 lerr = getKeyByIndex_immm([keyn], val, ky, def, lDisp) 1930 1911 END FUNCTION getKeyByIndex_i1mm 1931 1912 !============================================================================================================================== 1932 LOGICAL FUNCTION getKeyByIndex_r1mm(keyn, val, ky, nam, def, lDisp) RESULT(lerr) 1933 CHARACTER(LEN=*), INTENT(IN) :: keyn 1934 REAL, ALLOCATABLE, INTENT(OUT) :: val(:) 1935 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1936 CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: nam(:) 1937 REAL, OPTIONAL, INTENT(IN) :: def 1938 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1939 lerr = getKeyByIndex_rmmm([keyn], val, ky, nam, def, lDisp) 1913 LOGICAL FUNCTION getKeyByIndex_r1mm(keyn, val, ky, def, lDisp) RESULT(lerr) 1914 CHARACTER(LEN=*), INTENT(IN) :: keyn 1915 REAL, ALLOCATABLE, INTENT(OUT) :: val(:) 1916 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1917 REAL, OPTIONAL, INTENT(IN) :: def 1918 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1919 lerr = getKeyByIndex_rmmm([keyn], val, ky, def, lDisp) 1940 1920 END FUNCTION getKeyByIndex_r1mm 1941 1921 !============================================================================================================================== 1942 LOGICAL FUNCTION getKeyByIndex_l1mm(keyn, val, ky, nam, def, lDisp) RESULT(lerr) 1943 CHARACTER(LEN=*), INTENT(IN) :: keyn 1944 LOGICAL, ALLOCATABLE, INTENT(OUT) :: val(:) 1945 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1946 CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: nam(:) 1947 LOGICAL, OPTIONAL, INTENT(IN) :: def 1948 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1949 lerr = getKeyByIndex_lmmm([keyn], val, ky, nam, def, lDisp) 1922 LOGICAL FUNCTION getKeyByIndex_l1mm(keyn, val, ky, def, lDisp) RESULT(lerr) 1923 CHARACTER(LEN=*), INTENT(IN) :: keyn 1924 LOGICAL, ALLOCATABLE, INTENT(OUT) :: val(:) 1925 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1926 LOGICAL, OPTIONAL, INTENT(IN) :: def 1927 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1928 lerr = getKeyByIndex_lmmm([keyn], val, ky, def, lDisp) 1950 1929 END FUNCTION getKeyByIndex_l1mm 1951 1930 !============================================================================================================================== 1952 1931 !============================================================================================================================== 1953 LOGICAL FUNCTION getKeyByIndex_smmm(keyn, val, ky, nam, def, lDisp) RESULT(lerr) 1954 CHARACTER(LEN=*), INTENT(IN) :: keyn(:) 1955 CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) :: val(:) 1956 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1957 CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: nam(:) 1958 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: def 1959 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1932 LOGICAL FUNCTION getKeyByIndex_smmm(keyn, val, ky, def, lDisp) RESULT(lerr) 1933 CHARACTER(LEN=*), INTENT(IN) :: keyn(:) 1934 CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) :: val(:) 1935 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1936 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: def 1937 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1960 1938 !------------------------------------------------------------------------------------------------------------------------------ 1961 1939 CHARACTER(LEN=maxlen) :: s 1962 CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:)1963 1940 INTEGER :: iq, nq(3), k 1964 1941 LOGICAL :: lD, l(3) … … 1967 1944 lerr = .TRUE. 1968 1945 IF(PRESENT(ky)) THEN; val = fgetKey(ky) !--- "ky" 1969 ELSE IF(ALLOCATED(tracers)) THEN; val = fgetKey(tracers(:) %keys)!--- "tracers"1946 ELSE IF(ALLOCATED(tracers)) THEN; val = fgetKey(tracers(:)) !--- "tracers" 1970 1947 IF(lerr .AND. ASSOCIATED(isotope)) val = fgetKey(isotope%keys(:)) !--- "isotope" 1971 1948 END IF 1972 IF(.NOT.lerr) THEN; IF(PRESENT(nam)) nam = tname; RETURN; END IF1949 IF(.NOT.lerr) RETURN 1973 1950 IF(.NOT.PRESENT(def)) THEN; CALL msg('No '//TRIM(s)//' found', modname, lD); RETURN; END IF 1974 1951 … … 1991 1968 INTEGER :: iq 1992 1969 lerr = SIZE(ky) == 0; IF(lerr) RETURN 1993 tname = ky%name1994 1970 val = [(fgetKeyIdx(iq, keyn(:), ky, ler(iq)), iq = 1, SIZE(ky))] 1995 1971 lerr = ANY(ler) … … 1998 1974 END FUNCTION getKeyByIndex_smmm 1999 1975 !============================================================================================================================== 2000 LOGICAL FUNCTION getKeyByIndex_immm(keyn, val, ky, nam, def, lDisp) RESULT(lerr) 2001 CHARACTER(LEN=*), INTENT(IN) :: keyn(:) 2002 INTEGER, ALLOCATABLE, INTENT(OUT) :: val(:) 2003 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2004 CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: nam(:) 2005 INTEGER, OPTIONAL, INTENT(IN) :: def 2006 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1976 LOGICAL FUNCTION getKeyByIndex_immm(keyn, val, ky, def, lDisp) RESULT(lerr) 1977 CHARACTER(LEN=*), INTENT(IN) :: keyn(:) 1978 INTEGER, ALLOCATABLE, INTENT(OUT) :: val(:) 1979 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1980 INTEGER, OPTIONAL, INTENT(IN) :: def 1981 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2007 1982 !------------------------------------------------------------------------------------------------------------------------------ 2008 1983 CHARACTER(LEN=maxlen) :: s 2009 1984 CHARACTER(LEN=maxlen), ALLOCATABLE :: svals(:), tname(:) 2010 1985 LOGICAL, ALLOCATABLE :: ll(:) 2011 IF( PRESENT(def)) lerr = getKeyByIndex_smmm(keyn, svals, ky, tname,int2str(def), lDisp)2012 IF(.NOT.PRESENT(def)) lerr = getKeyByIndex_smmm(keyn, svals, ky, tname,lDisp=lDisp)1986 IF( PRESENT(def)) lerr = getKeyByIndex_smmm(keyn, svals, ky, int2str(def), lDisp) 1987 IF(.NOT.PRESENT(def)) lerr = getKeyByIndex_smmm(keyn, svals, ky, lDisp=lDisp) 2013 1988 IF(lerr) RETURN 2014 1989 val = str2int(svals) 2015 ll = val == -HUGE(1) 2016 lerr = ANY(ll); IF(.NOT.lerr) THEN; IF(PRESENT(nam)) nam = tname; RETURN; END IF 1990 ll = val == -HUGE(1) .AND. (SIZE(svals) /=1 .OR. svals(1) /= '') 1991 lerr = ANY(ll); IF(.NOT.lerr) RETURN 1992 IF(getKeyByIndex_smmm(['name'], tname, ky)) RETURN 2017 1993 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(strStack(PACK(tname, MASK=ll)))//' is not' 2018 1994 CALL msg(TRIM(s)//' an integer: '//TRIM(strStack(svals, MASK=ll)), modname, lerr) 2019 IF(.NOT.lerr .AND. PRESENT(nam)) nam = tname2020 1995 END FUNCTION getKeyByIndex_immm 2021 1996 !============================================================================================================================== 2022 LOGICAL FUNCTION getKeyByIndex_rmmm(keyn, val, ky, nam, def, lDisp) RESULT(lerr) 2023 CHARACTER(LEN=*), INTENT(IN) :: keyn(:) 2024 REAL, ALLOCATABLE, INTENT(OUT) :: val(:) 2025 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2026 CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: nam(:) 2027 REAL, OPTIONAL, INTENT(IN) :: def 2028 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1997 LOGICAL FUNCTION getKeyByIndex_rmmm(keyn, val, ky, def, lDisp) RESULT(lerr) 1998 CHARACTER(LEN=*), INTENT(IN) :: keyn(:) 1999 REAL, ALLOCATABLE, INTENT(OUT) :: val(:) 2000 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2001 REAL, OPTIONAL, INTENT(IN) :: def 2002 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2029 2003 !------------------------------------------------------------------------------------------------------------------------------ 2030 2004 CHARACTER(LEN=maxlen) :: s 2031 2005 CHARACTER(LEN=maxlen), ALLOCATABLE :: svals(:), tname(:) 2032 2006 LOGICAL, ALLOCATABLE :: ll(:) 2033 IF( PRESENT(def)) lerr = getKeyByIndex_smmm(keyn, svals, ky, tname,real2str(def), lDisp)2034 IF(.NOT.PRESENT(def)) lerr = getKeyByIndex_smmm(keyn, svals, ky, tname,lDisp=lDisp)2007 IF( PRESENT(def)) lerr = getKeyByIndex_smmm(keyn, svals, ky, real2str(def), lDisp) 2008 IF(.NOT.PRESENT(def)) lerr = getKeyByIndex_smmm(keyn, svals, ky, lDisp=lDisp) 2035 2009 IF(lerr) RETURN 2036 2010 val = str2real(svals) 2037 ll = val == -HUGE(1.) 2038 lerr = ANY(ll); IF(.NOT.lerr) THEN; IF(PRESENT(nam)) nam = tname; RETURN; END IF 2011 ll = val == -HUGE(1.) .AND. (SIZE(svals) /=1 .OR. svals(1) /= '') 2012 lerr = ANY(ll); IF(.NOT.lerr) RETURN 2013 IF(getKeyByIndex_smmm(['name'], tname, ky)) RETURN 2039 2014 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(strStack(PACK(tname, MASK=ll)))//' is not a' 2040 2015 CALL msg(TRIM(s)//' a real: '//TRIM(strStack(svals, MASK=ll)), modname) 2041 2016 END FUNCTION getKeyByIndex_rmmm 2042 2017 !============================================================================================================================== 2043 LOGICAL FUNCTION getKeyByIndex_lmmm(keyn, val, ky, nam, def, lDisp) RESULT(lerr) 2044 CHARACTER(LEN=*), INTENT(IN) :: keyn(:) 2045 LOGICAL, ALLOCATABLE, INTENT(OUT) :: val(:) 2046 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2047 CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: nam(:) 2048 LOGICAL, OPTIONAL, INTENT(IN) :: def 2049 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2018 LOGICAL FUNCTION getKeyByIndex_lmmm(keyn, val, ky, def, lDisp) RESULT(lerr) 2019 CHARACTER(LEN=*), INTENT(IN) :: keyn(:) 2020 LOGICAL, ALLOCATABLE, INTENT(OUT) :: val(:) 2021 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2022 LOGICAL, OPTIONAL, INTENT(IN) :: def 2023 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2050 2024 !------------------------------------------------------------------------------------------------------------------------------ 2051 2025 CHARACTER(LEN=maxlen) :: s … … 2053 2027 LOGICAL, ALLOCATABLE :: ll(:) 2054 2028 INTEGER, ALLOCATABLE :: ivals(:) 2055 IF( PRESENT(def)) lerr = getKeyByIndex_smmm(keyn, svals, ky, tname,bool2str(def), lDisp)2056 IF(.NOT.PRESENT(def)) lerr = getKeyByIndex_smmm(keyn, svals, ky, tname,lDisp=lDisp)2029 IF( PRESENT(def)) lerr = getKeyByIndex_smmm(keyn, svals, ky, bool2str(def), lDisp) 2030 IF(.NOT.PRESENT(def)) lerr = getKeyByIndex_smmm(keyn, svals, ky, lDisp=lDisp) 2057 2031 IF(lerr) RETURN 2058 2032 ivals = str2bool(svals) 2059 ll = ivals == -1 2060 lerr = ANY(ll); IF(.NOT.lerr) THEN; val = ivals == 1; IF(PRESENT(nam)) nam = tname; RETURN; END IF 2033 ll = ivals == -1 .AND. (SIZE(svals) /=1 .OR. svals(1) /= '') 2034 lerr = ANY(ll); IF(.NOT.lerr) RETURN 2035 IF(getKeyByIndex_smmm(['name'], tname, ky)) RETURN 2061 2036 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(strStack(tname, MASK=ll))//' is not' 2062 2037 CALL msg(TRIM(s)//' a boolean: '//TRIM(strStack(svals, MASK=ll)), modname) … … 2071 2046 !=== TRY TO GET THE KEY NAMED "key" FOR THE TRACER NAMED "tname" IN: === 2072 2047 !=== * ARGUMENT "ky" DATABASE IF SPECIFIED ; OTHERWISE: === 2073 !=== * IN INTERNAL TRACERS DATABASE "tracers(:) %keys" (IF UNFOUND, IN INTERNAL ISOTOPES DATABASE "isotope%keys(:)")===2048 !=== * IN INTERNAL TRACERS DATABASE "tracers(:)" (IF UNFOUND, IN INTERNAL ISOTOPES DATABASE "isotope%keys(:)") === 2074 2049 !=== THE RETURNED VALUE (STRING, AN INTEGER, A REAL OR A LOGICAL) CAN BE EITHER: === 2075 2050 !=== * A SCALAR === … … 2133 2108 tnam = strHead(delPhase(tname),'_',.TRUE.) !--- Remove phase and tag 2134 2109 IF(lerr .AND. PRESENT(ky)) val = fgetKey(ky) !--- "ky" 2135 IF(lerr .AND. ALLOCATED (tracers)) val = fgetKey(tracers(:) %keys)!--- "tracers"2110 IF(lerr .AND. ALLOCATED (tracers)) val = fgetKey(tracers(:)) !--- "tracers" 2136 2111 IF(lerr .AND. ASSOCIATED(isotope)) val = fgetKey(isotope%keys(:)) !--- "isotope" 2137 2112 IF(lerr .AND. PRESENT(def)) THEN … … 2145 2120 CHARACTER(LEN=maxlen) FUNCTION fgetKey(ky) RESULT(val) 2146 2121 TYPE(keys_type), INTENT(IN) :: ky(:) 2147 lerr = SIZE(ky) == 02148 IF(lerr) RETURN2149 val = fgetKeyIdx(strIdx(ky%name, tname), [keyn], ky, lerr)2150 IF(lerr) val = fgetKeyIdx(strIdx(ky%name, tnam), [keyn], ky, lerr)2151 2122 CHARACTER(LEN=maxlen), ALLOCATABLE :: tname_all(:) 2123 lerr = SIZE(ky) == 0; IF(lerr) RETURN 2124 lerr = getKey('name', tname_all, ky); IF(lerr) RETURN 2125 val = fgetKeyIdx(strIdx(tname_all, tname), [keyn], ky, lerr) 2126 IF(lerr) val = fgetKeyIdx(strIdx(tname_all, tnam ), [keyn], ky, lerr) 2152 2127 END FUNCTION fgetKey 2153 2128 … … 2166 2141 IF(lerr) RETURN 2167 2142 val = str2int(sval) 2168 lerr = val == -HUGE(1) 2143 lerr = val == -HUGE(1) .AND. sval /= '' 2169 2144 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(tname)//' is not' 2170 2145 CALL msg(TRIM(s)//' an integer: '//TRIM(sval), modname, lerr) … … 2183 2158 IF(lerr) RETURN 2184 2159 val = str2real(sval) 2185 lerr = val == -HUGE(1.) 2160 lerr = val == -HUGE(1.) .AND. sval /= '' 2186 2161 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(tname)//' is not' 2187 2162 CALL msg(TRIM(s)//' a real: '//TRIM(sval), modname, lerr) … … 2201 2176 IF(lerr) RETURN 2202 2177 ival = str2bool(sval) 2203 lerr = ival == -1 2178 lerr = ival == -1 .AND. sval /= '' 2204 2179 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(tname)//' is not' 2205 2180 CALL msg(TRIM(s)//' a boolean: '//TRIM(sval), modname, lerr) … … 2236 2211 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 2237 2212 val = str2int(svals) 2238 lerr = ANY(val == -HUGE(1)) 2213 lerr = ANY(val == -HUGE(1)) .AND. sval /= '' 2239 2214 s = 'key "'//TRIM(keyn)//'" of '//TRIM(tname)//' is not' 2240 2215 CALL msg(TRIM(s)//' an integer: '//TRIM(sval), modname, lerr) … … 2256 2231 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 2257 2232 val = str2real(svals) 2258 lerr = ANY(val == -HUGE(1.)) 2233 lerr = ANY(val == -HUGE(1.)) .AND. sval /= '' 2259 2234 s = 'key "'//TRIM(keyn)//'" of '//TRIM(tname)//' is not' 2260 2235 CALL msg(TRIM(s)//' a real: '//TRIM(sval), modname, lerr) … … 2277 2252 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 2278 2253 ivals = str2bool(svals) 2279 lerr = ANY(ivals == -1) 2254 lerr = ANY(ivals == -1) .AND. sval /= '' 2280 2255 s = 'key "'//TRIM(keyn)//'" of '//TRIM(tname)//' is not' 2281 2256 CALL msg(TRIM(s)//' a boolean: '//TRIM(sval), modname, lerr) … … 2312 2287 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 2313 2288 val = str2int(svals) 2314 lerr = ANY(val == -HUGE(1)) 2289 lerr = ANY(val == -HUGE(1)) .AND. sval /= '' 2315 2290 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(tname)//' is not' 2316 2291 CALL msg(TRIM(s)//' an integer: '//TRIM(sval), modname, lerr) … … 2332 2307 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 2333 2308 val = str2real(svals) 2334 lerr = ANY(val == -HUGE(1.)) 2309 lerr = ANY(val == -HUGE(1.)) .AND. sval /= '' 2335 2310 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(tname)//' is not' 2336 2311 CALL msg(TRIM(s)//' a real: '//TRIM(sval), modname, lerr) … … 2353 2328 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 2354 2329 ivals = str2bool(svals) 2355 lerr = ANY(ivals == -1) 2330 lerr = ANY(ivals == -1) .AND. sval /= '' 2356 2331 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(tname)//' is not' 2357 2332 CALL msg(TRIM(s)//' a boolean: '//TRIM(sval), modname, lerr) … … 2412 2387 lerr = .TRUE. 2413 2388 IF(PRESENT(ky)) THEN; val = fgetKey(ky) !--- "ky" 2414 ELSE IF(ALLOCATED(tracers)) THEN; val = fgetKey(tracers(:) %keys)!--- "tracers"2389 ELSE IF(ALLOCATED(tracers)) THEN; val = fgetKey(tracers(:)) !--- "tracers" 2415 2390 IF(lerr .AND. ASSOCIATED(isotope)) val = fgetKey(isotope%keys(:)) !--- "isotope" 2416 2391 END IF … … 2427 2402 TYPE(keys_type), INTENT(IN) :: ky(:) 2428 2403 LOGICAL, ALLOCATABLE :: ler(:) 2429 lerr = SIZE(ky) == 0; IF(lerr) RETURN 2404 CHARACTER(LEN=maxlen), ALLOCATABLE :: tname_all(:) 2405 lerr = SIZE(ky) == 0; IF(lerr) RETURN 2406 lerr = getKey('name', tname_all, ky); IF(lerr) RETURN 2430 2407 ALLOCATE(ler(SIZE(tname))) 2431 val = [(fgetKeyIdx(strIdx( ky(:)%name, tname(iq)), keyn, ky, ler(iq)), iq = 1, SIZE(tname))]2408 val = [(fgetKeyIdx(strIdx(tname_all, tname(iq)), keyn, ky, ler(iq)), iq = 1, SIZE(tname))] 2432 2409 lerr = ANY(ler) 2433 2410 END FUNCTION fgetKey … … 2449 2426 IF(lerr) RETURN 2450 2427 val = str2int(svals) 2451 ll = val == -HUGE(1) 2428 ll = val == -HUGE(1) .AND. (SIZE(svals) /=1 .OR. svals(1) /= '') 2452 2429 lerr = ANY(ll); IF(.NOT.lerr) RETURN 2453 2430 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(strStack(tname, MASK=ll))//' is not' … … 2469 2446 IF(lerr) RETURN 2470 2447 val = str2real(svals) 2471 ll = val == -HUGE(1.) 2448 ll = val == -HUGE(1.) .AND. (SIZE(svals) /=1 .OR. svals(1) /= '') 2472 2449 lerr = ANY(ll); IF(.NOT.lerr) RETURN 2473 2450 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(strStack(tname, MASK=ll))//' is not' … … 2490 2467 IF(lerr) RETURN 2491 2468 ivals = str2bool(svals) 2492 ll = ivals == -1 2469 ll = ivals == -1 .AND. (SIZE(svals) /=1 .OR. svals(1) /= '') 2493 2470 lerr = ANY(ll); IF(.NOT.lerr) THEN; val = ivals == 1; RETURN; END IF 2494 2471 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(strStack(tname, MASK=ll))//' is not' … … 2502 2479 !============================================================================================================================== 2503 2480 SUBROUTINE setKeysDBase(tracers_, isotopes_, isotope_) 2504 TYPE( trac_type), OPTIONAL, INTENT(IN) :: tracers_(:)2481 TYPE(keys_type), OPTIONAL, INTENT(IN) :: tracers_(:) 2505 2482 TYPE(isot_type), OPTIONAL, INTENT(IN) :: isotopes_(:) 2506 2483 TYPE(isot_type), OPTIONAL, INTENT(IN) :: isotope_ … … 2511 2488 IF(PRESENT(isotopes_)) THEN; isotopes = isotopes_; ELSE; ALLOCATE(isotopes(0)); END IF 2512 2489 IF(PRESENT(isotope_ )) THEN 2513 ix = strIdx(isotopes(:)% parent, isotope_%parent)2490 ix = strIdx(isotopes(:)%name, isotope_%name) 2514 2491 IF(ix /= 0) THEN 2515 2492 isotopes(ix) = isotope_ … … 2522 2499 !============================================================================================================================== 2523 2500 SUBROUTINE getKeysDBase(tracers_, isotopes_, isotope_) 2524 TYPE( trac_type), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: tracers_(:)2501 TYPE(keys_type), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: tracers_(:) 2525 2502 TYPE(isot_type), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: isotopes_(:) 2526 2503 TYPE(isot_type), OPTIONAL, INTENT(OUT) :: isotope_ … … 2529 2506 IF(PRESENT( tracers_)) THEN; tracers_ = tracers; ELSE; ALLOCATE( tracers_(0)); END IF 2530 2507 IF(PRESENT(isotopes_)) THEN; isotopes_ = isotopes; ELSE; ALLOCATE(isotopes_(0)); END IF 2531 IF(PRESENT(isotope_ )) THEN; ix = strIdx(isotopes(:)% parent, isotope%parent); IF(ix /= 0) isotope_=isotopes(ix); END IF2508 IF(PRESENT(isotope_ )) THEN; ix = strIdx(isotopes(:)%name, isotope%name); IF(ix /= 0) isotope_=isotopes(ix); END IF 2532 2509 END SUBROUTINE getKeysDBase 2533 2510 !============================================================================================================================== … … 2605 2582 CHARACTER(LEN=*), INTENT(IN) :: tname 2606 2583 TYPE(keys_type), INTENT(IN) :: keys 2607 TYPE( trac_type), ALLOCATABLE, INTENT(INOUT) :: tracs(:)2608 TYPE( trac_type), ALLOCATABLE :: tr(:)2584 TYPE(keys_type), ALLOCATABLE, INTENT(INOUT) :: tracs(:) 2585 TYPE(keys_type), ALLOCATABLE :: tr(:) 2609 2586 CHARACTER(LEN=maxlen), ALLOCATABLE :: tnames(:) 2610 2587 INTEGER :: nt, ix 2611 2588 IF(ALLOCATED(tracs)) THEN 2612 lerr = getKey('name', tnames, ky=tracs(:) %keys); IF(lerr) RETURN2589 lerr = getKey('name', tnames, ky=tracs(:)); IF(lerr) RETURN 2613 2590 nt = SIZE(tracs) 2614 2591 ix = strIdx(tnames, tname) … … 2622 2599 ix = 1; ALLOCATE(tracs(1)) 2623 2600 END IF 2624 CALL addKey('name', tname, tracs(ix)%keys) 2625 tracs(ix)%name = tname 2626 tracs(ix)%keys = keys 2601 CALL addKey('name', tname, tracs(ix)) 2602 tracs(ix) = keys 2627 2603 2628 2604 END FUNCTION addTracer_1 … … 2639 2615 LOGICAL FUNCTION delTracer_1(tname, tracs) RESULT(lerr) 2640 2616 CHARACTER(LEN=*), INTENT(IN) :: tname 2641 TYPE( trac_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: tracs(:)2642 TYPE( trac_type), ALLOCATABLE :: tr(:)2617 TYPE(keys_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: tracs(:) 2618 TYPE(keys_type), ALLOCATABLE :: tr(:) 2643 2619 CHARACTER(LEN=maxlen), ALLOCATABLE :: tnames(:) 2644 2620 INTEGER :: nt, ix … … 2646 2622 IF(fmsg('Can''t remove tracer "'//TRIM(tname)//'" from an empty tracers descriptor', modname, lerr)) RETURN 2647 2623 nt = SIZE(tracs) 2648 lerr = getKey('name', tnames, ky=tracs(:) %keys); IF(lerr) RETURN2624 lerr = getKey('name', tnames, ky=tracs(:)); IF(lerr) RETURN 2649 2625 ix = strIdx(tnames, tname) 2650 2626 CALL msg('Removing tracer "' //TRIM(tname)//'"', modname, ix /= 0) … … 2690 2666 2691 2667 !============================================================================================================================== 2692 !============ CONVERT WATER-DERIVED NAMES FROM FORMER TO CURRENT CONVENTION ; OTHER NAMES ARE LEFT UNTOUCHED ================== 2693 !======= NAMES STRUCTURE: H2O[<phase>][_<isotope>][_<tag>] (<phase> from "old_phases", <isotope> from "oldH2OIso") ============ 2668 !======== CONVERT WATER-DERIVED NAMES FROM FORMER TO CURRENT CONVENTION & VICE VERSA ; OTHER NAMES ARE LEFT UNTOUCHED ========= 2669 !===== OLD NAMES STRUCTURE: H2O[<phase>][_<isotope>][_<tag>] (<phase> from "old_phases", <isotope> from "oldH2OIso") == 2670 !==== NEW NAMES STRUCTURE: <var>[<phase_sep><phase>][_<tag>] (<phase> from "known_phases", <var>='H2O' or from "newH2OIso") == 2694 2671 !============================================================================================================================== 2695 2672 CHARACTER(LEN=maxlen) FUNCTION old2newH2O_1(oldName, iPhase) RESULT(newName) … … 2724 2701 END FUNCTION old2newH2O_m 2725 2702 !============================================================================================================================== 2726 2727 2728 !==============================================================================================================================2729 !============ CONVERT WATER-DERIVED NAMES FROM CURRENT TO FORMER CONVENTION ; OTHER NAMES ARE LEFT UNTOUCHED ==================2730 !==== NAMES STRUCTURE: <var>[<phase_sep><phase>][_<tag>] (<phase> from "known_phases", <var> = 'H2O' or from "newH2OIso") =====2731 !==============================================================================================================================2732 2703 CHARACTER(LEN=maxlen) FUNCTION new2oldH2O_1(newName, iPhase) RESULT(oldName) 2733 2704 CHARACTER(LEN=*), INTENT(IN) :: newName -
LMDZ6/trunk/libf/phylmd/infotrac_phy.F90
r5003 r5183 3 3 MODULE infotrac_phy 4 4 5 USE strings_mod, ONLY: msg, fmsg, maxlen, cat, dispTable, int2str, bool2str, strStack, strParse, strIdx 6 USE readTracFiles_mod, ONLY: trac_type, readTracersFiles, tracers, setGeneration, itZonIso, nzone, tran0, isoZone, & 7 delPhase, niso, getKey, isot_type, processIsotopes, isotope, maxTableWidth, iqIsoPha, nphas, ixIso, isoPhas, & 8 addPhase, iH2O, addKey, isoSelect, testTracersFiles, isoKeys, indexUpdate, iqWIsoPha, nbIso, ntiso, isoName, isoCheck 5 USE strings_mod, ONLY: msg, maxlen, cat, dispTable, int2str, bool2str, strStack, strParse, strCount, strIdx 6 USE readTracFiles_mod, ONLY: readTracersFiles, maxTableWidth, tisot=>isot_type, addPhase, addKey, iH2O, & 7 indexUpdate, keys_type, testTracersFiles, processIsotopes, trac=>tracers, delPhase, getKey, tran0 8 USE readTracFiles_mod, ONLY: new2oldH2O 9 9 10 IMPLICIT NONE 10 11 … … 16 17 PUBLIC :: nqtot, nbtr, nqo, nqCO2, nqtottr !--- Main dimensions 17 18 PUBLIC :: conv_flg, pbl_flg !--- Convection & boundary layer activation keys 18 #ifdef CPP_StratAer 19 PUBLIC :: new2oldH2O !--- For backwards compatibility in phyetat0 20 PUBLIC :: addPhase, delPhase !--- Add/remove the phase from the name of a tracer 21 #if defined CPP_StratAer || defined REPROBUS 19 22 PUBLIC :: nbtr_bin, nbtr_sulgas !--- Number of aerosols bins and sulfur gases for StratAer model 20 23 PUBLIC :: id_OCS_strat, id_SO2_strat, id_H2SO4_strat, id_BIN01_strat, id_TEST_strat 21 24 #endif 22 25 23 !=== FOR WATER24 PUBLIC :: ivap, iliq, isol25 26 !=== FOR ISOTOPES: General 26 27 PUBLIC :: isot_type, nbIso !--- Derived type, full isotopes families database + nb of families 27 PUBLIC :: isoSelect, ixIso !--- Isotopes family selection tool + selected family index28 PUBLIC :: isoSelect, ixIso, isoFamilies !--- Isotopes families selection tool + selected index + list 28 29 !=== FOR ISOTOPES: Specific to water 29 PUBLIC :: iH2O !--- H2O isotopes class index 30 PUBLIC :: iH2O !--- Value of "ixIso" for "H2O" isotopes class 31 PUBLIC :: ivap, iliq, isol 30 32 !=== FOR ISOTOPES: Depending on the selected isotopes family 31 PUBLIC :: isotope, isoKeys !--- Selected isotopes database + associated keys (cf. getKey) 32 PUBLIC :: isoName, isoZone, isoPhas !--- Isotopes and tagging zones names, phases 33 PUBLIC :: niso, nzone, nphas, ntiso !--- " " numbers + isotopes & tagging tracers number 34 PUBLIC :: itZonIso !--- idx "it" (in "isoName(1:niso)") = function(tagging idx, isotope idx) 35 PUBLIC :: iqIsoPha !--- idx "iq" (in "qx") = function(isotope idx, phase idx) + aliases 36 PUBLIC :: iqWIsoPha !--- Same as iqIsoPha but with normal water phases 37 33 PUBLIC :: isotope !--- Selected isotopes database (argument of getKey) 34 PUBLIC :: isoKeys, isoName, isoZone, isoPhas !--- Isotopes keys & names, tagging zones names, phases 35 PUBLIC :: niso, ntiso, nzone, nphas !--- Number of " " 36 PUBLIC :: itZonIso !--- index "it" in "isoName(1:niso)" = f(tagging idx, isotope idx) 37 PUBLIC :: iqIsoPha !--- index "iq" in "qx" = f(isotope idx, phase idx) 38 PUBLIC :: iqWIsoPha !--- Same as iqIsoPha but with normal water phases 38 39 PUBLIC :: isoCheck !--- Run isotopes checking routines 39 40 !=== FOR BOTH TRACERS AND ISOTOPES … … 43 44 ! |--------------------+-----------------------+-----------------+---------------+----------------------------| 44 45 ! | water in different | water tagging | water isotopes | other tracers | additional tracers moments | 45 ! | phases: H2O_[gls ]| isotopes | | | for higher order schemes |46 ! | phases: H2O_[glsrb]| isotopes | | | for higher order schemes | 46 47 ! |--------------------+-----------------------+-----------------+---------------+----------------------------| 47 48 ! | | | | | | … … 57 58 ! |-----------------------------------------------------------------------------------------------------------| 58 59 ! NOTES FOR THIS TABLE: 59 ! * Used "niso", "nzone" and "ntiso" are components of "isotopes(ip)" for water (isotopes(ip)% parent== 'H2O'),60 ! * Used "niso", "nzone" and "ntiso" are components of "isotopes(ip)" for water (isotopes(ip)%name == 'H2O'), 60 61 ! since water is so far the sole tracers family, except passive CO2, removed from the main tracers table. 61 62 ! * For water, "nqo" is equal to the more general field "isotopes(ip)%nphas". 62 63 ! * "niso", "nzone", "ntiso", "nphas" are defined for other isotopic tracers families, if any. 64 ! * If you deal with an isotopes family other than "H2O" ("Sulf" in the example), a good practice is to keep 65 ! track of the isotopes class (of its index) before switching to it at the beginning of the dedicated code: 66 ! - first time (use selection by name and compute the corresponding index iSulf) : 67 ! i0=ixIso; IF(.NOT.isoSelect('Sulf')) CALL abort_physic("Can't select isotopes class", modname, 1); iS=ixIso 68 ! - next times (use selection by index - "iS" has been computed at first call): 69 ! i0=ixIso; IF(.NOT.isoSelect(iS)) CALL abort_physic("Can't select isotopes class", modname, 1) 70 ! and to switch back to the original category when you're done with "Sulf": 71 ! IF(.NOT.isoSelect(i0)) CALL abort_physic("Can't select isotopes class", modname, 1) 72 ! to restore the original isotopes category (before dealing with "Sulf" (most of the time "H2O"). 63 73 ! 64 74 !=== DERIVED TYPE EMBEDDING MOST OF THE TRACERS-RELATED QUANTITIES (LENGTH: nqtot) … … 68 78 ! |-------------+------------------------------------------------------+-------------+------------------------+ 69 79 ! | name | Name (short) | tname | | 80 ! | keys | key/val pairs accessible with "getKey" routine | / | | 70 81 ! | gen0Name | Name of the 1st generation ancestor | / | | 71 82 ! | parent | Name of the parent | / | | 72 83 ! | longName | Long name (with adv. scheme suffix) for outputs | ttext | | 73 84 ! | type | Type (so far: tracer or tag) | / | tracer,tag | 74 ! | phase | Phases list ("g"as / "l"iquid / "s"olid) | / | [g][l][s] | 85 ! | phase | Phases list ("g"as / "l"iquid / "s"olid | | [g|l|s|r|b] | 86 ! | | "r"(cloud) / "b"lowing) | / | | 75 87 ! | component | Name(s) of the merged/cumulated section(s) | / | coma-separated names | 76 88 ! | iGeneration | Generation (>=1) | / | | … … 79 91 ! | nqDescen | Number of the descendants (all generations) | nqdesc | 1:nqtot | 80 92 ! | nqChildren | Number of childs (1st generation only) | nqfils | 1:nqtot | 81 ! | keys | key/val pairs accessible with "getKey" routine | / | | 82 ! | isAdvected | advected tracers flag (.TRUE. if iadv >= 0) | / | nqtrue .TRUE. values | 83 ! | isInPhysics | tracers not extracted from the main table in physics | / | nqtottr .TRUE. values | 93 ! | isAdvected | Advected tracers flag (.TRUE. if iadv >= 0) | / | nqtrue .TRUE. values | 94 ! | isInPhysics | Tracers not extracted from the main table in physics | / | nqtottr .TRUE. values | 84 95 ! | iso_iGroup | Isotopes group index in isotopes(:) | / | 1:nbIso | 85 96 ! | iso_iName | Isotope name index in isotopes(iso_iGroup)%trac(:) | iso_indnum | 1:niso | … … 93 104 ! | entry | length | Meaning | Former name | Possible values | 94 105 ! |-----------------+--------------------------------------------------+--------------------+-----------------+ 95 ! | parent | Parent tracer (isotopes family name)| | |106 ! | name | Name of the isotopes class (family) | | | 96 107 ! | keys | niso | Isotopes keys/values pairs list + number | | | 97 108 ! | trac | ntiso | Isotopes + tagging tracers list + number | / | ntraciso | | 98 109 ! | zone | nzone | Geographic tagging zones list + number | / | ntraceurs_zone | | 99 ! | phase | nphas | Phases list + number | | [g ][l][s], 1:3|110 ! | phase | nphas | Phases list + number | | [g|l|s|r|b] 1:5 | 100 111 ! | iqIsoPha | Index in "qx" = f(name(1:ntiso)),phas) | iqiso | 1:nqtot | 101 ! | iqWIsoPha | Index in "qx" = f(name(1:ntiso)),phas) | iqiso| 1:nqtot |112 ! | iqWIsoPha | Index in "qx" = f(name(1:ntiso+nqo)),phas) | ? | 1:nqtot | 102 113 ! | itZonIso | Index in "trac(1:ntiso)"= f(zone, name(1:niso)) | index_trac | 1:ntiso | 103 114 ! +-----------------+--------------------------------------------------+--------------------+-----------------+ 104 115 116 !------------------------------------------------------------------------------------------------------------------------------ 117 TYPE :: trac_type !=== TYPE FOR A SINGLE TRACER NAMED "name" 118 CHARACTER(LEN=maxlen) :: name = '' !--- Name of the tracer 119 TYPE(keys_type) :: keys !--- <key>=<val> pairs vector (general container) 120 CHARACTER(LEN=maxlen) :: gen0Name = '' !--- First generation ancestor name 121 CHARACTER(LEN=maxlen) :: parent = '' !--- Parent name 122 CHARACTER(LEN=maxlen) :: longName = '' !--- Long name (with advection scheme suffix) 123 CHARACTER(LEN=maxlen) :: type = 'tracer' !--- Type (so far: 'tracer' / 'tag') 124 CHARACTER(LEN=maxlen) :: phase = 'g' !--- Phase ('g'as / 'l'iquid / 's'olid) 125 CHARACTER(LEN=maxlen) :: component = '' !--- Coma-separated list of components (Ex: lmdz,inca) 126 INTEGER :: iGeneration = -1 !--- Generation number (>=0) 127 INTEGER :: iqParent = 0 !--- Parent index 128 INTEGER, ALLOCATABLE :: iqDescen(:) !--- Descendants index (in growing generation order) 129 INTEGER :: nqDescen = 0 !--- Number of descendants (all generations) 130 INTEGER :: nqChildren = 0 !--- Number of children (first generation) 131 LOGICAL :: isAdvected = .FALSE. !--- "true" tracers: iadv > 0. COUNT(isAdvected )=nqtrue 132 LOGICAL :: isInPhysics = .TRUE. !--- "true" tracers: in tr_seri. COUNT(isInPhysics)=nqtottr 133 INTEGER :: iso_iGroup = 0 !--- Isotopes group index in isotopes(:) 134 INTEGER :: iso_iName = 0 !--- Isotope name index in isotopes(iso_iGroup)%trac(:) 135 INTEGER :: iso_iZone = 0 !--- Isotope zone index in isotopes(iso_iGroup)%zone(:) 136 INTEGER :: iso_iPhase = 0 !--- Isotope phase index in isotopes(iso_iGroup)%phase 137 END TYPE trac_type 138 !------------------------------------------------------------------------------------------------------------------------------ 139 TYPE :: isot_type !=== TYPE FOR THE ISOTOPES FAMILY DESCENDING ON TRACER "name" 140 CHARACTER(LEN=maxlen) :: name !--- Isotopes family name (ex: H2O) 141 TYPE(keys_type), ALLOCATABLE :: keys(:) !--- Isotopes keys/values pairs list (length: niso) 142 LOGICAL :: check=.FALSE. !--- Flag for checking routines triggering 143 CHARACTER(LEN=maxlen), ALLOCATABLE :: trac(:) !--- Isotopes + tagging tracers list (length: ntiso) 144 CHARACTER(LEN=maxlen), ALLOCATABLE :: zone(:) !--- Geographic tagging zones names list (length: nzone) 145 CHARACTER(LEN=maxlen) :: phase = 'g' !--- Phases list: [g|l|s|r|b] (length: nphas) 146 INTEGER :: niso = 0 !--- Number of isotopes, excluding tagging tracers 147 INTEGER :: ntiso = 0 !--- Number of isotopes, including tagging tracers 148 INTEGER :: nzone = 0 !--- Number of geographic tagging zones 149 INTEGER :: nphas = 0 !--- Number of phases 150 INTEGER, ALLOCATABLE :: iqIsoPha(:,:) !--- Idx in "tracers(1:nqtot)" = f( name(1:ntiso) ,phas) 151 INTEGER, ALLOCATABLE :: iqWIsoPha(:,:) !--- Idx in "tracers(1:nqtot)" = f([H2O,name(1:ntiso)],phas) 152 INTEGER, ALLOCATABLE :: itZonIso(:,:) !--- Idx in "trac(1:ntiso)" = f(zone,name(1:niso)) 153 END TYPE isot_type 154 !------------------------------------------------------------------------------------------------------------------------------ 155 INTERFACE isoSelect; MODULE PROCEDURE isoSelectByIndex, isoSelectByName; END INTERFACE isoSelect 156 !------------------------------------------------------------------------------------------------------------------------------ 157 158 !=== INDICES FOR WATER 159 INTEGER, SAVE :: ivap, iliq, isol 160 !$OMP THREADPRIVATE(ivap, iliq, isol) 161 105 162 !=== DIMENSIONS OF THE TRACERS TABLES AND OTHER SCALAR VARIABLES 106 INTEGER, SAVE :: nqtot, &!--- Tracers nb in dynamics (incl. higher moments + H2O)107 nbtr, &!--- Tracers nb in physics (excl. higher moments + H2O)108 nqo, &!--- Number of water phases163 INTEGER, SAVE :: nqtot, & !--- Tracers nb in dynamics (incl. higher moments + H2O) 164 nbtr, & !--- Tracers nb in physics (excl. higher moments + H2O) 165 nqo, & !--- Number of water phases 109 166 nqtottr, & !--- Number of tracers passed to phytrac (TO BE DELETED ?) 110 167 nqCO2 !--- Number of tracers of CO2 (ThL) … … 112 169 !$OMP THREADPRIVATE(nqtot, nbtr, nqo, nqtottr, nqCO2, type_trac) 113 170 114 !=== INDICES OF WATER 115 INTEGER, SAVE :: ivap,iliq,isol ! Indices for vap, liq and ice 116 !$OMP THREADPRIVATE(ivap,iliq,isol) 171 !=== NUMBER AND LIST OF DEFINED ISOTOPES FAMILIES 172 INTEGER, SAVE :: nbIso !--- Number of defined isotopes classes 173 CHARACTER(LEN=maxlen), SAVE, ALLOCATABLE :: isoFamilies(:) !--- Generation 0 tracer name for each isotopes family (nbIso) 174 !$OMP THREADPRIVATE(isoFamilies) 175 176 !=== QUANTITIES RELATED TO THE CURRENTLY SELECTED ISOTOPES CLASS (USUALLY H2O) 177 TYPE(isot_type), SAVE, POINTER :: isotope !--- Selected isotopes database (=isotopes(ixIso)) 178 TYPE(keys_type), SAVE, POINTER :: isoKeys(:) !--- Database to get isotopes keys using "getKey" (niso) 179 CHARACTER(LEN=maxlen), SAVE, POINTER :: isoName(:), & !--- Isotopes list including tagging tracers, no phase (ntiso) 180 isoZone(:), & !--- Geographic tagging zones list (nzone) 181 isoPhas !--- Used phases names ([g|l|s|r|b]) (nphas) 182 INTEGER, SAVE, POINTER :: itZonIso(:,:), & !--- Idx "it" in isoName(1:niso) = f(tagging idx, isotope idx) 183 iqIsoPha(:,:), & !--- Idx "iq" in qx = f(isotope idx, phase idx) 184 iqWIsoPha(:,:) !--- Idx "iq" in qx = f([parent trac,isotope idx], phase idx) 185 INTEGER, SAVE :: ixIso, & !--- Idx in "isoFamilies" of currently selectd class 186 niso, & !--- Number of isotopes 187 ntiso, & !--- Number of isotopes + tagging tracers 188 nzone, & !--- Number of tagging zones 189 nphas !--- Number of phases 190 LOGICAL, SAVE :: isoCheck !--- Isotopes checking routines triggering flag 191 !$OMP THREADPRIVATE(isotope, isoKeys, isoName, isoZone, isoPhas, itZonIso, iqIsoPha, iqWIsoPha, niso, ntiso, nzone, nphas, isoCheck) 117 192 118 193 !=== VARIABLES FOR INCA 119 INTEGER, SAVE, ALLOCATABLE :: conv_flg(:), & !--- Convection activation ; needed for INCA (nbtr)120 pbl_flg(:) !--- Boundary layer activation ; needed for INCA(nbtr)194 INTEGER, DIMENSION(:), SAVE, ALLOCATABLE :: & 195 conv_flg, pbl_flg !--- Convection / boundary layer activation (nbtr) 121 196 !$OMP THREADPRIVATE(conv_flg, pbl_flg) 122 197 123 #ifdef CPP_StratAer 198 !=== TRACERS/ISOTOPES DESCRIPTORS: EFFECTIVE STORAGE (LOCAL DERIVED TYPES) 199 TYPE(trac_type), SAVE, ALLOCATABLE, TARGET :: tracers(:) 200 TYPE(isot_type), SAVE, ALLOCATABLE, TARGET :: isotopes(:) 201 !$OMP THREADPRIVATE(tracers, isotopes) 202 203 #if defined CPP_StratAer || defined REPROBUS 124 204 !=== SPECIFIC TO STRATOSPHERIC AEROSOLS (CK/OB) 125 205 INTEGER, SAVE :: nbtr_bin, nbtr_sulgas !--- number of aerosols bins and sulfur gases for StratAer model … … 133 213 SUBROUTINE init_infotrac_phy 134 214 USE ioipsl_getin_p_mod, ONLY: getin_p 215 USE mod_phys_lmdz_para, ONLY: is_master, is_omp_master 135 216 #ifdef REPROBUS 136 217 USE CHEM_REP, ONLY: Init_chem_rep_trac … … 161 242 !------------------------------------------------------------------------------------------------------------------------------ 162 243 ! Local variables 163 INTEGER, ALLOCATABLE :: hadv(:), vadv(:) 244 INTEGER, ALLOCATABLE :: hadv(:), vadv(:), itmp(:) !--- Horizontal/vertical transport scheme number 164 245 #ifdef INCA 165 246 INTEGER, ALLOCATABLE :: had (:), hadv_inca(:), conv_flg_inca(:), &!--- Variables specific to INCA … … 173 254 CHARACTER(LEN=2) :: suff(9) !--- Suffixes for schemes of order 3 or 4 (Prather) 174 255 CHARACTER(LEN=3) :: descrq(30) !--- Advection scheme description tags 175 CHARACTER(LEN=maxlen) :: msg1, texp, ttp !--- Stringfor messages and expanded tracers type256 CHARACTER(LEN=maxlen) :: msg1, texp, ttp, ky !--- Strings for messages and expanded tracers type 176 257 INTEGER :: fType !--- Tracers description file type ; 0: none 177 258 !--- 1/2/3: "traceur.def"/"tracer.def"/"tracer_*.def" 178 259 INTEGER :: nqtrue !--- Tracers nb from tracer.def (no higher order moments) 179 260 INTEGER :: iad !--- Advection scheme number 180 INTEGER :: iq, jq, nt, im, nm, k!--- Indexes and temporary variables261 INTEGER :: iq, jq, it, nt, im, nm !--- Indexes and temporary variables 181 262 LOGICAL :: lerr, lInit 263 TYPE(keys_type), ALLOCATABLE, TARGET :: tra(:) !--- Tracers descriptor as in readTracFiles_mod 264 TYPE(tisot), ALLOCATABLE :: iso(:) !--- Isotopes descriptor as in readTracFiles_mod 182 265 TYPE(trac_type), ALLOCATABLE, TARGET :: ttr(:) 183 TYPE(trac_type), POINTER :: t 1, t(:)184 CHARACTER(LEN=maxlen), ALLOCATABLE :: types_trac(:) !--- Keyword for tracers type(s), parsed version185 266 TYPE(trac_type), POINTER :: t(:), t1 267 TYPE(keys_type), POINTER :: k(:) 268 CHARACTER(LEN=maxlen), ALLOCATABLE :: types_trac(:) !--- Keywords for tracers type(s), parsed version 186 269 CHARACTER(LEN=*), PARAMETER :: modname="init_infotrac_phy" 187 270 !------------------------------------------------------------------------------------------------------------------------------ … … 195 278 196 279 CALL getin_p('type_trac',type_trac) 197 198 lerr=strParse(type_trac, '|', types_trac, n=nt) 199 IF (nt .GT. 1) THEN 200 IF (nt .GT. 2) CALL abort_physic(modname, 'you need to modify type_trac, this version is not supported by lmdz', 1) 201 IF (nt .EQ. 2) type_trac=types_trac(2) 202 ENDIF 203 204 205 CALL msg('type_trac = "'//TRIM(type_trac)//'"', modname) 206 lInit = .NOT.ALLOCATED(tracers) 280 CALL msg('type_trac = "'//TRIM(type_trac)//'"', modname, is_master) 281 IF(strCount(type_trac, '|', nt)) CALL abort_physic(modname, 'Could''nt parse the "type_trac" string with delimiter "|"', 1) 282 IF(nt >= 3) CALL abort_physic(modname, 'you need to modify type_trac, this version is not supported by lmdz', 1) 283 IF(strParse(type_trac, '|', types_trac, n=nt)) CALL abort_physic(modname, "couldn't parse "//'"type_trac"', 1) 284 IF(nt == 2) type_trac = types_trac(2) ! TO BE DELETED SOON 285 286 lInit = .NOT.ALLOCATED(trac) 207 287 208 288 !############################################################################################################################## 209 IF(lInit ) THEN !=== SKIPED IF ALREADY DONE IN dyn3d_common/infotrac ####289 IF(lInit .AND. is_master) THEN !=== SKIPED IF ALREADY DONE 210 290 !############################################################################################################################## 211 291 !--- MESSAGE ABOUT THE CHOSEN CONFIGURATION … … 240 320 !############################################################################################################################## 241 321 242 nqCO2 = COUNT( [type_trac == 'inco', type_trac == 'co2i'] ) 243 244 !============================================================================================================================== 245 ! 1) Get the numbers of: true (first order only) tracers "nqtrue", water tracers "nqo" (vapor/liquid/solid) 246 !============================================================================================================================== 247 texp = type_trac !=== EXPANDED VERSION OF "type_trac", WITH "|" SEPARATOR 322 !============================================================================================================================== 323 ! 0) DETERMINE THE TYPE OF THE INPUT TRACERS DESCRIPTION FILE AND READ IT ; TRANSFER THE NEEDED QUANTITIES TO LOCAL "tracers". 324 !============================================================================================================================== 325 texp = type_trac !=== EXPANDED (WITH "|" SEPARATOR) "type_trac" 248 326 IF(texp == 'inco') texp = 'co2i|inca' 249 327 IF(texp /= 'lmdz') texp = 'lmdz|'//TRIM(texp) 250 251 !=== DETERMINE THE TYPE OF THE INPUT TRACERS DESCRIPTION FILE 252 IF(testTracersFiles(modname, texp, fType, lInit)) CALL abort_physic(modname, 'problem with tracers file(s)',1) 253 328 IF(testTracersFiles(modname, texp, fType, lInit.AND.is_master)) CALL abort_physic(modname, 'problem with tracers file(s)',1) 254 329 ttp = type_trac; IF(fType /= 1) ttp = texp 330 !--------------------------------------------------------------------------------------------------------------------------- 331 IF(fType == 0) CALL abort_physic(modname, 'Missing "traceur.def", "tracer.def" or "tracer_<keyword>.def tracers file.',1) 332 !--------------------------------------------------------------------------------------------------------------------------- 333 IF(fType == 1 .AND. ANY(['inca', 'inco'] == type_trac)) & !=== FOUND OLD STYLE INCA "traceur.def" 334 CALL abort_physic(modname, 'retro-compatibility with old-style INCA traceur.def files has been disabled.', 1) 335 !--------------------------------------------------------------------------------------------------------------------------- 255 336 256 337 !############################################################################################################################## 257 IF(lInit ) THEN258 IF(readTracersFiles(ttp, lRepr=type_trac=='repr')) CALL abort_physic(modname, 'problem with tracers file(s)',1)338 IF(lInit .AND. is_omp_master) THEN 339 IF(readTracersFiles(ttp, tra, type_trac == 'repr')) CALL abort_physic(modname, 'problem with tracers file(s)',1) 259 340 ELSE 260 CALL msg('No tracers description file(s) reading needed: already done in the dynamics', modname) 261 END IF 341 tra = trac 342 END IF 343 CALL msg('No tracers description file(s) reading needed: already done', modname, .NOT.lInit.AND.is_master) 262 344 !############################################################################################################################## 263 345 264 !--------------------------------------------------------------------------------------------------------------------------- 265 IF(fType == 0) CALL abort_physic(modname, 'Missing tracers file: "traceur.def", "tracer.def" or "tracer_<keyword>.def file.',1) 266 !--------------------------------------------------------------------------------------------------------------------------- 267 IF(fType == 1 .AND. ANY(['inca','inco']==type_trac) .AND. lInit) THEN !=== FOUND OLD STYLE INCA "traceur.def" 268 !--------------------------------------------------------------------------------------------------------------------------- 346 !--- POPULATE SOME EXPLICIT (ACCESSIBLE THROUGH "%") KEYS OF THE LOCAL TRACERS DESCRIPTION DERIVED TYPE 347 ! To be defined: iqParent, iq/nqDescen, nqChildren (in indexUpdate), longName, iso_i*, isAdvected, isInPhysics (later) 348 ALLOCATE(tracers(SIZE(tra))) 349 DO iq = 1, SIZE(tra); t1 => tracers(iq) 350 t1%keys = tra(iq) 351 msg1 = '" for tracer nr. '//TRIM(int2str(iq)) 352 ky='name '; IF(getKey(ky, t1%name, iq, tra)) CALL abort_physic(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1) 353 msg1 = '" for "'//TRIM(t1%name)//'"' 354 ky='gen0Name '; IF(getKey(ky, t1%gen0Name, iq, tra)) CALL abort_physic(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1) 355 ky='parent '; IF(getKey(ky, t1%parent, iq, tra)) CALL abort_physic(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1) 356 ky='type '; IF(getKey(ky, t1%type, iq, tra)) CALL abort_physic(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1) 357 ky='phase '; IF(getKey(ky, t1%phase, iq, tra)) CALL abort_physic(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1) 358 ky='component '; IF(getKey(ky, t1%component, iq, tra)) CALL abort_physic(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1) 359 ky='iGeneration'; IF(getKey(ky, t1%iGeneration, iq, tra)) CALL abort_physic(modname, 'No key "'//TRIM(ky)//TRIM(msg1), 1) 360 END DO 361 362 !============================================================================================================================== 363 ! 1) Get various numbers: "nqtrue" (first order only tracers), "nqo" (water phases), 'nbtr' (tracers passed to physics), etc. 364 !============================================================================================================================== 365 nqtrue = SIZE(tracers) !--- "true" tracers 366 nqo = COUNT(tracers(:)%component == 'lmdz' .AND. delPhase(tracers(:)%name) == 'H2O') !--- Water phases 367 nbtr = nqtrue-COUNT(tracers(:)%component == 'lmdz' .AND. delPhase(tracers(:)%gen0Name) == 'H2O') !--- Passed to phytrac 368 nqCO2 = COUNT( [type_trac == 'inco', type_trac == 'co2i'] ) 269 369 #ifdef INCA 270 nqo = SIZE(tracers) - nqCO2 271 CALL Init_chem_inca_trac(nqINCA) !--- Get nqINCA from INCA 272 nbtr = nqINCA + nqCO2 !--- Number of tracers passed to phytrac 273 nqtrue = nbtr + nqo !--- Total number of "true" tracers 274 IF(ALL([2,3] /= nqo)) CALL abort_physic(modname, 'Only 2 or 3 water phases allowed ; found nqo='//TRIM(int2str(nqo)), 1) 275 ALLOCATE(hadv(nqtrue), hadv_inca(nqINCA), conv_flg_inca(nqINCA), solsym_inca(nqINCA)) 276 ALLOCATE(vadv(nqtrue), vadv_inca(nqINCA), pbl_flg_inca(nqINCA)) 277 CALL init_transport(solsym_inca, conv_flg_inca, pbl_flg_inca, hadv_inca, vadv_inca) 278 ALLOCATE(ttr(nqtrue)) 279 ttr(1:nqo+nqCO2) = tracers 280 ttr(1 : nqo )%component = 'lmdz' 281 ttr(1+nqo:nqCO2+nqo )%component = 'co2i' 282 ttr(1+nqo+nqCO2:nqtrue)%component = 'inca' 283 ttr(1+nqo :nqtrue)%name = [('CO2 ', k=1, nqCO2), solsym_inca] 284 ttr(1+nqo+nqCO2:nqtrue)%parent = tran0 285 ttr(1+nqo+nqCO2:nqtrue)%phase = 'g' 286 lerr = getKey('hadv', had, ky=tracers(:)%keys) 287 lerr = getKey('vadv', vad, ky=tracers(:)%keys) 288 hadv(1:nqo+nqCO2) = had(:); hadv(1+nqo+nqCO2:nqtrue) = hadv_inca 289 vadv(1:nqo+nqCO2) = vad(:); vadv(1+nqo+nqCO2:nqtrue) = vadv_inca 290 CALL MOVE_ALLOC(FROM=ttr, TO=tracers) 291 DO iq = 1, nqtrue 292 t1 => tracers(iq) 293 CALL addKey('name', t1%name, t1%keys) 294 CALL addKey('component', t1%component, t1%keys) 295 CALL addKey('parent', t1%parent, t1%keys) 296 CALL addKey('phase', t1%phase, t1%keys) 297 END DO 298 IF(setGeneration(tracers)) CALL abort_physic(modname,'See below',1) !- SET FIELDS %iGeneration, %gen0Name 299 DEALLOCATE(had, hadv_inca, vad, vadv_inca, conv_flg_inca, pbl_flg_inca, solsym_inca) 300 #endif 301 !--------------------------------------------------------------------------------------------------------------------------- 302 ELSE !=== OTHER CASES (OLD OR NEW FORMAT, NO INCA MODULE) 303 !--------------------------------------------------------------------------------------------------------------------------- 304 nqo = COUNT(delPhase(tracers(:)%name) == 'H2O' & 305 .AND. tracers(:)%component == 'lmdz') !--- Number of water phases 306 nqtrue = SIZE(tracers) !--- Total number of "true" tracers 307 nbtr = nqtrue-COUNT(delPhase(tracers(:)%gen0Name) == 'H2O' & 308 .AND. tracers(:)%component == 'lmdz') !--- Number of tracers passed to phytrac 309 #ifdef INCA 310 nqINCA = COUNT(tracers(:)%component == 'inca') 311 #endif 312 lerr = getKey('hadv', hadv, ky=tracers(:)%keys) 313 lerr = getKey('vadv', vadv, ky=tracers(:)%keys) 314 !--------------------------------------------------------------------------------------------------------------------------- 315 END IF 316 !--------------------------------------------------------------------------------------------------------------------------- 317 318 !--- Transfert the number of tracers to Reprobus 370 nqINCA = COUNT(tracers(:)%component == 'inca') 371 #endif 319 372 #ifdef REPROBUS 320 CALL Init_chem_rep_trac(nbtr, nqo, tracers(:)%name) 321 #endif 322 323 !############################################################################################################################## 324 IF(lInit) THEN !=== SKIPED IF ALREADY DONE IN dyn3d_common/infotrac #### 325 !############################################################################################################################## 373 CALL Init_chem_rep_trac(nbtr, nqo, tracers(:)%name) !--- Transfert the number of tracers to Reprobus 374 #endif 326 375 327 376 !============================================================================================================================== 328 377 ! 2) Calculate nqtot, number of tracers needed (greater if advection schemes 20 or 30 have been chosen). 329 378 !============================================================================================================================== 379 IF(getKey('hadv', hadv, ky=tra)) CALL abort_physic(modname, 'missing key "hadv"', 1) 380 IF(getKey('vadv', vadv, ky=tra)) CALL abort_physic(modname, 'missing key "vadv"', 1) 330 381 DO iq = 1, nqtrue 331 382 IF( hadv(iq)<20 .OR. (ANY(hadv(iq)==[20,30]) .AND. hadv(iq)==vadv(iq)) ) CYCLE … … 348 399 !============================================================================================================================== 349 400 ALLOCATE(ttr(nqtot)) 350 jq = nqtrue+1 ; tracers(:)%iadv = -1401 jq = nqtrue+1 351 402 DO iq = 1, nqtrue 352 403 t1 => tracers(iq) … … 359 410 IF(iad == -1) CALL abort_physic(modname, msg1, 1) 360 411 361 !--- SET FIELDS %longName, %isAdvected, %isInPhysics412 !--- SET FIELDS longName, isAdvected, isInPhysics 362 413 t1%longName = t1%name; IF(iad > 0) t1%longName=TRIM(t1%name)//descrq(iad) 363 414 t1%isAdvected = iad >= 0 364 t1%isInPhysics= delPhase(t1%gen0Name) /= 'H2O' & 365 .OR. t1%component /= 'lmdz' !=== OTHER EXCEPTIONS TO BE ADDED: CO2i, SURSATURATED WATER CLOUD... 415 t1%isInPhysics= delPhase(t1%gen0Name) /= 'H2O' .OR. t1%component /= 'lmdz' !=== MORE EXCEPTIONS ? CO2i, SURSAT CLOUD H2O 366 416 ttr(iq) = t1 367 417 … … 372 422 IF(nm == 0) CYCLE !--- No higher moments 373 423 ttr(jq+1:jq+nm) = t1 374 ttr(jq+1:jq+nm)%name = [(TRIM(t1%name) //'-'//TRIM(suff(im)), im=1, nm) ] 375 ttr(jq+1:jq+nm)%parent = [(TRIM(t1%parent) //'-'//TRIM(suff(im)), im=1, nm) ] 376 ttr(jq+1:jq+nm)%longName = [(TRIM(t1%longName)//'-'//TRIM(suff(im)), im=1, nm) ] 377 ttr(jq+1:jq+nm)%isAdvected = [(.FALSE., im=1, nm) ] 424 ttr(jq+1:jq+nm)%name = [ (TRIM(t1%name) //'-'//TRIM(suff(im)), im=1, nm) ] 425 ttr(jq+1:jq+nm)%gen0Name = [ (TRIM(t1%name) //'-'//TRIM(suff(im)), im=1, nm) ] 426 ttr(jq+1:jq+nm)%parent = [ (TRIM(t1%parent) //'-'//TRIM(suff(im)), im=1, nm) ] 427 ttr(jq+1:jq+nm)%longName = [ (TRIM(t1%longName)//'-'//TRIM(suff(im)), im=1, nm) ] 428 ttr(jq+1:jq+nm)%isAdvected = [ (.FALSE., im=1, nm) ] 429 ttr(jq+1:jq+nm)%isInPhysics = [ (.FALSE., im=1, nm) ] 378 430 jq = jq + nm 379 431 END DO … … 381 433 CALL MOVE_ALLOC(FROM=ttr, TO=tracers) 382 434 383 !--- SET FIELDS %iqParent, %nqChildren, %iGeneration, %iqDescen, %nqDescen 384 IF(indexUpdate(tracers)) CALL abort_gcm(modname, 'problem when processing isotopes parameters', 1) 385 386 !############################################################################################################################## 387 END IF 388 !############################################################################################################################## 389 390 !############################################################################################################################## 391 IF(.NOT.lInit) THEN 392 !############################################################################################################################## 393 nqtot = SIZE(tracers) 394 !############################################################################################################################## 395 ELSE 396 !############################################################################################################################## 397 398 !=== READ PHYSICAL PARAMETERS FOR ISOTOPES 399 niso = 0; nzone = 0; nphas = nqo; ntiso = 0; isoCheck = .FALSE. 400 IF(processIsotopes()) CALL abort_physic(modname, 'Problem when processing isotopes parameters', 1) 401 402 !############################################################################################################################## 403 END IF 404 !############################################################################################################################## 435 !--- SET FIELDS iqParent, iqDescen, nqDescen, nqChildren 436 IF(indexUpdate(tracers%keys)) CALL abort_physic(modname, 'problem with tracers indices update', 1) 437 k => tracers(:)%keys 438 DO iq = 1, SIZE(tracers); t1 => tracers(iq); msg1 = '" for "'//TRIM(t1%name)//'"' 439 ky='iqParent '; IF(getKey(ky, t1%iqParent, iq, k)) CALL abort_physic(modname, 'missing key "'//TRIM(ky)//TRIM(msg1), 1) 440 ky='iqDescen '; IF(getKey(ky, t1%iqDescen, iq, k)) CALL abort_physic(modname, 'missing key "'//TRIM(ky)//TRIM(msg1), 1) 441 ky='nqDescen '; IF(getKey(ky, t1%nqDescen, iq, k)) CALL abort_physic(modname, 'missing key "'//TRIM(ky)//TRIM(msg1), 1) 442 ky='nqChildren'; IF(getKey(ky, t1%nqChildren, iq, k)) CALL abort_physic(modname, 'missing key "'//TRIM(ky)//TRIM(msg1), 1) 443 END DO 444 445 !=== DETERMINE ISOTOPES RELATED PARAMETERS ; DEFINE THE EXPLICIT KEYS iso_i* 446 IF(processIsotopes(tracers%keys, iso)) CALL abort_physic(modname, 'problem while processing isotopes parameters', 1) 447 448 !--- POPULATE SOME EXPLICIT (ACCESSIBLE THROUGH "%") KEYS OF THE LOCAL ISOTOPES DESCRIPTION DERIVED TYPE 449 nbIso = SIZE(iso) 450 ALLOCATE(isotopes(nbIso)) 451 IF(nbIso /= 0) THEN 452 k => tracers(:)%keys 453 IF(getKey('iso_iGroup', itmp, ky=k)) CALL abort_physic(modname, 'missing key "iso_iGroup"', 1); tracers%iso_iGroup = itmp 454 IF(getKey('iso_iName', itmp, ky=k)) CALL abort_physic(modname, 'missing key "iso_iName"', 1); tracers%iso_iName = itmp 455 IF(getKey('iso_iZone', itmp, ky=k)) CALL abort_physic(modname, 'missing key "iso_iZone"', 1); tracers%iso_iZone = itmp 456 IF(getKey('iso_iPhas', itmp, ky=k)) CALL abort_physic(modname, 'missing key "iso_iPhas"', 1); tracers%iso_iPhase = itmp 457 isotopes(:)%name = iso(:)%name !--- Isotopes family name (ex: H2O) 458 isotopes(:)%phase = iso(:)%phase !--- Phases list: [g][l][s] (length: nphas) 459 isotopes(:)%niso = iso(:)%niso !--- Number of isotopes, excluding tagging tracers 460 isotopes(:)%ntiso = iso(:)%ntiso !--- Number of isotopes, including tagging tracers 461 isotopes(:)%nzone = iso(:)%nzone !--- Number of geographic tagging zones 462 isotopes(:)%nphas = iso(:)%nphas !--- Number of phases 463 isotopes(:)%check = .FALSE. !--- Flag for checking routines triggering 464 CALL getin_p('ok_iso_verif', isotopes(:)%check) 465 DO it = 1, nbIso 466 isotopes(it)%keys = iso(it)%keys !--- Isotopes keys/values pairs list (length: niso) 467 isotopes(it)%trac = iso(it)%trac !--- Isotopes + tagging tracers list (length: ntiso) 468 isotopes(it)%zone = iso(it)%zone !--- Geographic tagging zones names list (length: nzone) 469 isotopes(it)%iqIsoPha = iso(it)%iqIsoPha(:,:) !--- Idx in "tracers(1:nqtot)" = f(name(1:ntiso)),phas) 470 isotopes(it)%iqWIsoPha= iso(it)%iqWIsoPha(:,:) !--- Idx in "tracers(1:nqtot)" = f([trPrnt,name(1:ntiso)],phas) 471 isotopes(it)%itZonIso = iso(it)%itZonIso(:,:) !--- Idx in "tracers(1:ntiso)" = f( zone,name(1:niso)) 472 END DO 473 IF(isoSelect(1, .TRUE.)) CALL abort_physic(modname, "Can't select the first isotopes family", 1) 474 IF(.NOT.isoSelect('H2O', .TRUE.)) iH2O = ixIso 475 END IF 476 isoFamilies = isotopes(:)%name 477 405 478 !--- Convection / boundary layer activation for all tracers 406 IF 407 IF (.NOT.ALLOCATED(pbl_flg)) ALLOCATE( pbl_flg(nbtr)); pbl_flg(1:nbtr) = 1479 IF(.NOT.ALLOCATED(conv_flg)) ALLOCATE(conv_flg(nbtr)); conv_flg(1:nbtr) = 1 480 IF(.NOT.ALLOCATED( pbl_flg)) ALLOCATE( pbl_flg(nbtr)); pbl_flg(1:nbtr) = 1 408 481 409 482 !--- Note: nqtottr can differ from nbtr when nmom/=0 … … 413 486 414 487 !=== DISPLAY THE RESULTS 488 IF(.NOT.is_master) RETURN 415 489 CALL msg('nqo = '//TRIM(int2str(nqo)), modname) 416 490 CALL msg('nbtr = '//TRIM(int2str(nbtr)), modname) … … 424 498 #endif 425 499 t => tracers 426 CALL msg('Information stored in infotrac_phy :', modname) 427 IF(dispTable('issssssssiiiiiiii', ['iq ', 'name', 'lNam', 'g0Nm', 'prnt', 'type', 'phas', 'comp', & 428 'isPh', 'iGen', 'iqPr', 'nqDe', 'nqCh', 'iGrp', 'iNam', 'iZon', 'iPha'], & 429 cat(t%name, t%longName, t%gen0Name, t%parent, t%type, t%phase, t%component, bool2str(t%isInPhysics)),& 500 CALL msg('Information stored in '//TRIM(modname)//': ', modname) 501 IF(dispTable('isssssssssiiiiiiii', ['iq ', 'name', 'lNam', 'g0Nm', 'prnt', 'type', 'phas', 'comp', & 502 'isPh', 'isAd', 'iGen', 'iqPr', 'nqDe', 'nqCh', 'iGrp', 'iNam', 'iZon', 'iPha'], & 503 cat(t%name, t%longName, t%gen0Name, t%parent, t%type, t%phase, t%component, & 504 bool2str(t%isInPhysics), bool2str(t%isAdvected)), & 430 505 cat([(iq, iq=1, nqtot)], t%iGeneration, t%iqParent, t%nqDescen, t%nqChildren, t%iso_iGroup, & 431 506 t%iso_iName, t%iso_iZone, t%iso_iPhase), nColMax=maxTableWidth, nHead=2, sub=modname)) & 432 507 CALL abort_physic(modname, "problem with the tracers table content", 1) 433 IF(niso > 0) THEN434 CALL msg('Where, for isotopes family "'//TRIM(isotope%parent)//'":', modname)435 CALL msg(' isoKeys%name = '//strStack(isoKeys%name), modname)436 CALL msg(' isoName = '//strStack(isoName), modname)437 CALL msg(' isoZone = '//strStack(isoZone), modname)438 CALL msg(' isoPhas = '//TRIM(isoPhas), modname)439 ELSE440 CALL msg('No isotopes identified.', modname)441 END IF442 443 #ifdef ISOVERIF444 CALL msg('iso_iName = '//strStack(int2str(PACK(tracers(:)%iso_iName, MASK=tracers(:)%iso_iGroup==iH2O))), modname)445 #endif446 508 #ifdef CPP_StratAer 447 509 IF (type_trac == 'coag') THEN … … 463 525 END IF 464 526 #endif 465 CALL msg('end', modname) 527 CALL msg('No isotopes identified.', modname, nbIso == 0) 528 IF(nbIso == 0) RETURN 529 DO it = 1, nbIso 530 IF(isoSelect(it, .TRUE.)) CALL abort_physic(modname, 'Problem when selecting isotopes class', 1) 531 CALL msg('For isotopes family "'//TRIM(isoFamilies(it))//'":', modname) 532 CALL msg(' isoName = '//strStack(isotope%trac), modname) 533 CALL msg(' isoZone = '//strStack(isotope%zone), modname) 534 CALL msg(' isoPhas = '// TRIM(isotope%phase), modname) 535 END DO 536 IF(isoSelect('H2O', .TRUE.)) THEN 537 IF(isoSelect(1, .TRUE.)) CALL abort_physic(modname, 'Problem when selecting isotopes class', 1) 538 ELSE 539 iH2O = ixIso 540 END IF 541 IF(ALLOCATED(isotope%keys(ixIso)%key)) & 542 CALL msg(' isoKeys('//TRIM(int2str(ixIso))//') = '//TRIM(strStack(isotope%keys(ixIso)%key)), modname) 543 #ifdef ISOVERIF 544 CALL msg('iso_iName(H2O) = '//TRIM(strStack(int2str(PACK(tracers%iso_iName, MASK=tracers%iso_iGroup==iH2O)))),modname) 545 #endif 466 546 467 547 END SUBROUTINE init_infotrac_phy 468 548 549 !============================================================================================================================== 550 LOGICAL FUNCTION isoSelectByName(iClass, lVerbose) RESULT(lerr) 551 IMPLICIT NONE 552 CHARACTER(LEN=*), INTENT(IN) :: iClass 553 LOGICAL, OPTIONAL, INTENT(IN) :: lVerbose 554 INTEGER :: iIso 555 LOGICAL :: lV 556 lV = .FALSE.; IF(PRESENT(lVerbose)) lV = lVerbose 557 iIso = strIdx(isotopes(:)%name, iClass) 558 lerr = iIso == 0 559 IF(lerr) THEN 560 niso = 0; ntiso = 0; nzone = 0; nphas = 0; isoCheck=.FALSE. 561 CALL msg('no isotope family named "'//TRIM(iClass)//'"', ll=lV) 562 RETURN 563 END IF 564 lerr = isoSelectByIndex(iIso, lV) 565 END FUNCTION isoSelectByName 566 !============================================================================================================================== 567 LOGICAL FUNCTION isoSelectByIndex(iIso, lVerbose) RESULT(lerr) 568 IMPLICIT NONE 569 INTEGER, INTENT(IN) :: iIso 570 LOGICAL, OPTIONAL, INTENT(IN) :: lVerbose 571 LOGICAL :: lV 572 lV = .FALSE.; IF(PRESENT(lVerbose)) lV = lVerbose 573 lerr = .FALSE. 574 IF(iIso == ixIso) RETURN !--- Nothing to do if the index is already OK 575 lerr = iIso<=0 .OR. iIso>SIZE(isotopes) 576 CALL msg('Inconsistent isotopes family index '//TRIM(int2str(iIso))//': should be > 0 and <= '& 577 //TRIM(int2str(SIZE(isotopes)))//'"', ll = lerr .AND. lV) 578 IF(lerr) RETURN 579 ixIso = iIso !--- Update currently selected family index 580 isotope => isotopes(ixIso) !--- Select corresponding component 581 isoKeys => isotope%keys; niso = isotope%niso 582 isoName => isotope%trac; ntiso = isotope%ntiso 583 isoZone => isotope%zone; nzone = isotope%nzone 584 isoPhas => isotope%phase; nphas = isotope%nphas 585 itZonIso => isotope%itZonIso; isoCheck = isotope%check 586 iqIsoPha => isotope%iqIsoPha 587 iqWIsoPha=> isotope%iqWIsoPha 588 END FUNCTION isoSelectByIndex 589 !============================================================================================================================== 590 469 591 END MODULE infotrac_phy -
LMDZ6/trunk/libf/phylmd/phyetat0_mod.F90
r5084 r5183 32 32 USE geometry_mod, ONLY: longitude_deg, latitude_deg 33 33 USE iostart, ONLY: close_startphy, get_field, get_var, open_startphy 34 USE infotrac_phy, ONLY: nqtot, nbtr, type_trac, tracers 35 USE readTracFiles_mod,ONLY: maxlen, new2oldH2O34 USE infotrac_phy, ONLY: nqtot, nbtr, type_trac, tracers, new2oldH2O 35 USE strings_mod, ONLY: maxlen 36 36 USE traclmdz_mod, ONLY: traclmdz_from_restart 37 37 USE carbon_cycle_mod, ONLY: carbon_cycle_init, carbon_cycle_cpl, carbon_cycle_tr, carbon_cycle_rad, co2_send, RCO2_glo -
LMDZ6/trunk/libf/phylmd/physiq_mod.F90
r5169 r5183 39 39 USE ioipsl_getin_p_mod, ONLY : getin_p 40 40 USE indice_sol_mod 41 USE infotrac_phy, ONLY: nqtot, nbtr, nqo, tracers, type_trac 42 USE readTracFiles_mod, ONLY: addPhase 41 USE infotrac_phy, ONLY: nqtot, nbtr, nqo, tracers, type_trac, addPhase 43 42 USE strings_mod, ONLY: strIdx 44 43 USE iophy -
LMDZ6/trunk/libf/phylmdiso/isotopes_mod.F90
r4982 r5183 4 4 MODULE isotopes_mod 5 5 USE strings_mod, ONLY: msg, real2str, int2str, bool2str, maxlen, strIdx, strStack 6 USE infotrac_phy, ONLY: isoName 6 USE infotrac_phy, ONLY: isoName, isoSelect, niso, ntiso, nbIso, isoFamilies 7 USE iso_params_mod 7 8 IMPLICIT NONE 8 9 INTERFACE get_in; MODULE PROCEDURE getinp_s, getinp_i, getinp_r, getinp_l; END INTERFACE get_in … … 11 12 !--- Contains all isotopic variables + their initialization 12 13 !--- Isotopes-specific routines are in isotopes_routines_mod to avoid circular dependencies with isotopes_verif_mod. 14 15 !--- Negligible lower thresholds: no need to check for absurd values under these lower limits 16 REAL, PARAMETER :: & 17 ridicule = 1e-12, & ! For mixing ratios 18 ridicule_rain = 1e-8, & ! For rain fluxes (rain, zrfl...) in kg/s <-> 1e-3 mm/day 19 ridicule_evap = ridicule_rain*1e-2, & ! For evaporations in kg/s <-> 1e-3 mm/day 20 ridicule_qsol = ridicule_rain, & ! For qsol in kg <-> 1e-8 kg 21 ridicule_snow = ridicule_qsol ! For snow in kg <-> 1e-8 kg 22 REAL, PARAMETER :: expb_max = 30.0 23 24 !--- Fractionation coefficients for H217O 25 REAL, PARAMETER :: fac_coeff_eq17_liq = 0.529, & 26 fac_coeff_eq17_ice = 0.529 27 28 !--- H218O reference 29 REAL, PARAMETER :: fac_enrichoce18 = 0.0005, alpha_liq_sol_O18 = 1.00291, & 30 talph1_O18 = 1137., talps1_O18 = 11.839, tkcin0_O18 = 0.006, & 31 talph2_O18 = -0.4156, talps2_O18 = -0.028244, tkcin1_O18 = 0.000285, & 32 talph3_O18 = -2.0667E-3, tdifrel_O18 = 1./0.9723, tkcin2_O18 = 0.00082 33 34 !--- Parameters that do not depend on the nature of water isotopes: 35 REAL, PARAMETER :: pxtmelt = 273.15 !--- temperature at which ice formation starts 36 REAL, PARAMETER :: pxtice = 273.15 - 10.0 !--- temperature at which all condensate is ice: 37 REAL, PARAMETER :: pxtmin = 273.15 - 120.0 !--- computation done only under -120°C 38 REAL, PARAMETER :: pxtmax = 273.15 + 60.0 !--- computation done only over +60°C 39 REAL, PARAMETER :: tdifexp = 0.58 !--- a constant for alpha_eff for equilibrium below cloud base: 40 REAL, PARAMETER :: tv0cin = 7.0 !--- wind threshold (m/s) for smooth/rough regime (Merlivat and Jouzel 1979) 41 REAL, PARAMETER :: musi = 1.0 !--- facteurs lambda et mu dans Si=musi-lambda*T 42 REAL, PARAMETER :: Kd = 2.5e-9 ! m2/s !--- diffusion in soil 43 REAL, PARAMETER :: rh_cste_surf_cond = 0.6 !--- cste_surf_cond case: rhs and/or Ts set to constants 44 REAL, PARAMETER :: T_cste_surf_cond = 288.0 13 45 14 46 !--- Isotopes indices (in [1,niso] ; non-existing => 0 index) … … 89 121 !--- Vectors of length "niso" 90 122 REAL, ALLOCATABLE, DIMENSION(:), SAVE :: & 91 tnat, toce, tcorr, tdifrel92 !$OMP THREADPRIVATE( tnat, toce, tcorr, tdifrel)123 alpha, tnat, toce, tcorr, tdifrel 124 !$OMP THREADPRIVATE(alpha, tnat, toce, tcorr, tdifrel) 93 125 REAL, ALLOCATABLE, DIMENSION(:), SAVE :: & 94 126 talph1, talph2, talph3, talps1, talps2 … … 100 132 alpha_liq_sol, Rdefault, Rmethox 101 133 !$OMP THREADPRIVATE(alpha_liq_sol, Rdefault, Rmethox) 102 ! REAL, SAVE :: fac_coeff_eq17_liq, fac_coeff_eq17_ice103 !!$OMP THREADPRIVATE(fac_coeff_eq17_liq, fac_coeff_eq17_ice)104 105 !--- H2[18]O reference106 REAL, PARAMETER :: fac_enrichoce18=0.0005107 REAL, PARAMETER :: alpha_liq_sol_O18=1.00291108 REAL, PARAMETER :: talph1_O18=1137.109 REAL, PARAMETER :: talph2_O18=-0.4156110 REAL, PARAMETER :: talph3_O18=-2.0667E-3111 REAL, PARAMETER :: talps1_O18=11.839112 REAL, PARAMETER :: talps2_O18=-0.028244113 REAL, PARAMETER :: tdifrel_O18=1./0.9723114 REAL, PARAMETER :: tkcin0_O18=0.006115 REAL, PARAMETER :: tkcin1_O18=0.000285116 REAL, PARAMETER :: tkcin2_O18=0.00082117 REAL, PARAMETER :: fac_coeff_eq17_liq=0.529118 REAL, PARAMETER :: fac_coeff_eq17_ice=0.529119 120 !---- Parameters that do not depend on the nature of water isotopes:121 REAL, PARAMETER :: pxtmelt = 273.15 ! temperature at which ice formation starts122 REAL, PARAMETER :: pxtice = 273.15-10.0 ! -- temperature at which all condensate is ice:123 REAL, PARAMETER :: pxtmin = 273.15 - 120.0 ! On ne calcule qu'au dessus de -120°C124 REAL, PARAMETER :: pxtmax = 273.15 + 60.0 ! On ne calcule qu'au dessus de +60°C125 REAL, PARAMETER :: tdifexp = 0.58 ! -- a constant for alpha_eff for equilibrium below cloud base:126 REAL, PARAMETER :: tv0cin = 7.0 ! wind threshold (m/s) for smooth/rough regime (Merlivat and Jouzel 1979)127 REAL, PARAMETER :: musi=1.0 ! facteurs lambda et mu dans Si=musi-lambda*T128 REAL, PARAMETER :: Kd=2.5e-9 ! m2/s ! diffusion dans le sol129 REAL, PARAMETER :: rh_cste_surf_cond = 0.6 ! cas où cste_surf_cond: on met rhs ou/et Ts cste pour voir130 REAL, PARAMETER :: T_cste_surf_cond = 288.0131 132 133 !--- Negligible lower thresholds: no need to check for absurd values under these lower limits134 REAL, PARAMETER :: &135 ridicule = 1e-12, & ! For mixing ratios136 ridicule_rain = 1e-8, & ! For rain fluxes (rain, zrfl...) in kg/s <-> 1e-3 mm/day137 ridicule_evap = ridicule_rain*1e-2, & ! For evaporations in kg/s <-> 1e-3 mm/day138 ridicule_qsol = ridicule_rain, & ! For qsol in kg <-> 1e-8 kg139 ridicule_snow = ridicule_qsol ! For snow in kg <-> 1e-8 kg140 REAL, PARAMETER :: expb_max = 30.0141 134 142 135 !--- Specific to HTO: … … 155 148 156 149 SUBROUTINE iso_init() 157 USE infotrac_phy, ONLY: ntiso, niso, getKey158 USE strings_mod, ONLY: maxlen159 150 IMPLICIT NONE 160 151 161 152 !=== Local variables: 162 INTEGER :: ixt 163 153 INTEGER :: ixt, ii, is 154 LOGICAL :: ltnat1 155 CHARACTER(LEN=maxlen) :: modname, sxt 164 156 165 157 !--- For H2[17]O … … 170 162 LOGICAL, PARAMETER :: ok_nocinsat = .FALSE. ! if T: no sursaturation effect for ice 171 163 LOGICAL, PARAMETER :: Rdefault_smow = .FALSE. ! if T: Rdefault=smow; if F: nul 172 LOGICAL, PARAMETER :: tnat1 = .TRUE. ! If T: all tnats are 1.173 164 174 165 !--- For [3]H 175 166 INTEGER :: iessai 176 177 CHARACTER(LEN=maxlen) :: modname, sxt178 167 179 168 modname = 'iso_init' … … 187 176 CALL msg('64: niso = '//TRIM(int2str(niso)), modname) 188 177 189 !--- Init de ntracisoOR: on ecrasera en cas de traceurs de tagging isotopiques 190 ! (nzone>0) si complications avec ORCHIDEE 191 ntracisoOR = ntiso 192 193 !--- Type of water isotopes: 194 iso_eau = strIdx(isoName, 'H216O'); CALL msg('iso_eau='//int2str(iso_eau), modname) 195 iso_HDO = strIdx(isoName, 'HDO'); CALL msg('iso_HDO='//int2str(iso_HDO), modname) 196 iso_O18 = strIdx(isoName, 'H218O'); CALL msg('iso_O18='//int2str(iso_O18), modname) 197 iso_O17 = strIdx(isoName, 'H217O'); CALL msg('iso_O17='//int2str(iso_O17), modname) 198 iso_HTO = strIdx(isoName, 'HTO'); CALL msg('iso_HTO='//int2str(iso_HTO), modname) 199 200 !--- Initialiaation: reading the isotopic parameters. 201 CALL get_in('lambda', lambda_sursat, 0.004) 202 CALL get_in('thumxt1', thumxt1, 0.75*1.2) 203 CALL get_in('ntot', ntot, 20, .FALSE.) 204 CALL get_in('h_land_ice', h_land_ice, 20., .FALSE.) 205 CALL get_in('P_veg', P_veg, 1.0, .FALSE.) 206 CALL get_in('bidouille_anti_divergence', bidouille_anti_divergence, .FALSE.) 207 CALL get_in('essai_convergence', essai_convergence, .FALSE.) 208 CALL get_in('initialisation_iso', initialisation_iso, 0) 209 210 ! IF(nzone>0 .AND. initialisation_iso==0) & 211 ! CALL get_in('initialisation_isotrac',initialisation_isotrac) 212 CALL get_in('modif_sst', modif_sst, 0) 213 CALL get_in('deltaTtest', deltaTtest, 0.0) !--- For modif_sst>=1 214 CALL get_in('deltaTtestpoles',deltaTtestpoles, 0.0) !--- For modif_sst>=2 215 CALL get_in( 'sstlatcrit', sstlatcrit, 30.0) !--- For modif_sst>=3 216 CALL get_in('dsstlatcrit', dsstlatcrit, 0.0) !--- For modif_sst>=3 178 DO ii = 1, nbIso 179 CALL msg('Can''t select isotopes class "'//TRIM(isoFamilies(ii))//'"', modname, isoSelect(ii, lVerbose=.TRUE.)) 180 181 !============================================================================================================================== 182 IF(isoFamilies(ii) == 'H2O') THEN 183 !============================================================================================================================== 184 !--- Init de ntracisoOR: on ecrasera en cas de traceurs de tagging isotopiques 185 ! (nzone>0) si complications avec ORCHIDEE 186 ntracisoOR = ntiso 187 188 !--- Type of water isotopes: 189 iso_eau = strIdx(isoName, 'H216O'); CALL msg('iso_eau='//int2str(iso_eau), modname) 190 iso_HDO = strIdx(isoName, 'HDO'); CALL msg('iso_HDO='//int2str(iso_HDO), modname) 191 iso_O18 = strIdx(isoName, 'H218O'); CALL msg('iso_O18='//int2str(iso_O18), modname) 192 iso_O17 = strIdx(isoName, 'H217O'); CALL msg('iso_O17='//int2str(iso_O17), modname) 193 iso_HTO = strIdx(isoName, 'HTO'); CALL msg('iso_HTO='//int2str(iso_HTO), modname) 194 195 !--- Initialisation: reading the isotopic parameters. 196 CALL get_in('lambda', lambda_sursat, 0.004); IF(ok_nocinsat) lambda_sursat = 0. 197 CALL get_in('thumxt1', thumxt1, 0.75*1.2) 198 CALL get_in('ntot', ntot, 20, .FALSE.) 199 CALL get_in('h_land_ice', h_land_ice, 20., .FALSE.) 200 CALL get_in('P_veg', P_veg, 1.0, .FALSE.) 201 CALL get_in('bidouille_anti_divergence', bidouille_anti_divergence, .FALSE.) 202 CALL get_in('essai_convergence', essai_convergence, .FALSE.) 203 CALL get_in('initialisation_iso', initialisation_iso, 0) 204 205 ! IF(nzone>0 .AND. initialisation_iso==0) & 206 ! CALL get_in('initialisation_isotrac',initialisation_isotrac) 207 CALL get_in('modif_sst', modif_sst, 0) 208 CALL get_in('deltaTtest', deltaTtest, 0.0) !--- For modif_sst>=1 209 CALL get_in('deltaTtestpoles',deltaTtestpoles, 0.0) !--- For modif_sst>=2 210 CALL get_in( 'sstlatcrit', sstlatcrit, 30.0) !--- For modif_sst>=3 211 CALL get_in('dsstlatcrit', dsstlatcrit, 0.0) !--- For modif_sst>=3 217 212 #ifdef ISOVERIF 218 CALL msg('iso_init 270: sstlatcrit='//real2str( sstlatcrit), modname, sstlatcrit < 0.0) !--- For modif_sst>=2219 CALL msg('iso_init 279: dsstlatcrit='//real2str(dsstlatcrit), modname, sstlatcrit < 0.0) !--- For modif_sst>=3220 IF(modif_sst >= 2 .AND. sstlatcrit < 0.0) STOP213 CALL msg('iso_init 270: sstlatcrit='//real2str( sstlatcrit), modname, sstlatcrit < 0.0) !--- For modif_sst>=2 214 CALL msg('iso_init 279: dsstlatcrit='//real2str(dsstlatcrit), modname, sstlatcrit < 0.0) !--- For modif_sst>=3 215 IF(modif_sst >= 2 .AND. sstlatcrit < 0.0) STOP 221 216 #endif 222 217 223 CALL get_in('modif_sic', modif_sic, 0) 224 IF(modif_sic >= 1) & 225 CALL get_in('deltasic', deltasic, 0.1) 226 227 CALL get_in('albedo_prescrit', albedo_prescrit, 0) 228 IF(albedo_prescrit == 1) THEN 229 CALL get_in('lon_min_albedo', lon_min_albedo, -200.) 230 CALL get_in('lon_max_albedo', lon_max_albedo, 200.) 231 CALL get_in('lat_min_albedo', lat_min_albedo, -100.) 232 CALL get_in('lat_max_albedo', lat_max_albedo, 100.) 233 END IF 234 CALL get_in('deltaP_BL', deltaP_BL, 10.0) 235 CALL get_in('ruissellement_pluie', ruissellement_pluie, 0) 236 CALL get_in('alphak_stewart', alphak_stewart, 1) 237 CALL get_in('tdifexp_sol', tdifexp_sol, 0.67) 238 CALL get_in('calendrier_guide', calendrier_guide, 0) 239 CALL get_in('cste_surf_cond', cste_surf_cond, 0) 240 CALL get_in('mixlen', mixlen, 35.0) 241 CALL get_in('evap_cont_cste', evap_cont_cste, 0) 242 CALL get_in('deltaO18_evap_cont', deltaO18_evap_cont,0.0) 243 CALL get_in('d_evap_cont', d_evap_cont, 0.0) 244 CALL get_in('nudge_qsol', nudge_qsol, 0) 245 CALL get_in('region_nudge_qsol', region_nudge_qsol, 1) 246 nlevmaxO17 = 50 247 CALL msg('nlevmaxO17='//TRIM(int2str(nlevmaxO17))) 248 CALL get_in('no_pce', no_pce, 0) 249 CALL get_in('A_satlim', A_satlim, 1.0) 250 CALL get_in('ok_restrict_A_satlim', ok_restrict_A_satlim, 0) 218 CALL get_in('modif_sic', modif_sic, 0) 219 IF(modif_sic >= 1) & 220 CALL get_in('deltasic', deltasic, 0.1) 221 222 CALL get_in('albedo_prescrit', albedo_prescrit, 0) 223 IF(albedo_prescrit == 1) THEN 224 CALL get_in('lon_min_albedo', lon_min_albedo, -200.) 225 CALL get_in('lon_max_albedo', lon_max_albedo, 200.) 226 CALL get_in('lat_min_albedo', lat_min_albedo, -100.) 227 CALL get_in('lat_max_albedo', lat_max_albedo, 100.) 228 END IF 229 CALL get_in('deltaO18_oce', deltaO18_oce, 0.0) 230 CALL get_in('deltaP_BL', deltaP_BL, 10.0) 231 CALL get_in('ruissellement_pluie', ruissellement_pluie, 0) 232 CALL get_in('alphak_stewart', alphak_stewart, 1) 233 CALL get_in('tdifexp_sol', tdifexp_sol, 0.67) 234 CALL get_in('calendrier_guide', calendrier_guide, 0) 235 CALL get_in('cste_surf_cond', cste_surf_cond, 0) 236 CALL get_in('mixlen', mixlen, 35.0) 237 CALL get_in('evap_cont_cste', evap_cont_cste, 0) 238 CALL get_in('deltaO18_evap_cont', deltaO18_evap_cont,0.0) 239 CALL get_in('d_evap_cont', d_evap_cont, 0.0) 240 CALL get_in('nudge_qsol', nudge_qsol, 0) 241 CALL get_in('region_nudge_qsol', region_nudge_qsol, 1) 242 nlevmaxO17 = 50 243 CALL msg('nlevmaxO17='//TRIM(int2str(nlevmaxO17))) 244 CALL get_in('no_pce', no_pce, 0) 245 CALL get_in('A_satlim', A_satlim, 1.0) 246 CALL get_in('ok_restrict_A_satlim', ok_restrict_A_satlim, 0) 251 247 #ifdef ISOVERIF 252 CALL msg(' 315: A_satlim='//real2str(A_satlim), modname, A_satlim > 1.0)253 IF(A_satlim > 1.0) STOP248 CALL msg(' 315: A_satlim='//real2str(A_satlim), modname, A_satlim > 1.0) 249 IF(A_satlim > 1.0) STOP 254 250 #endif 255 ! CALL get_in('slope_limiterxy', slope_limiterxy, 2.0) 256 ! CALL get_in('slope_limiterz', slope_limiterz, 2.0) 257 CALL get_in('modif_ratqs', modif_ratqs, 0) 258 CALL get_in('Pcrit_ratqs', Pcrit_ratqs, 500.0) 259 CALL get_in('ratqsbasnew', ratqsbasnew, 0.05) 260 CALL get_in('fac_modif_evaoce', fac_modif_evaoce, 1.0) 261 CALL get_in('ok_bidouille_wake', ok_bidouille_wake, 0) 262 ! si oui, la temperature de cond est celle de l'environnement, pour eviter 263 ! bugs quand temperature dans ascendances convs est mal calculee 264 CALL get_in('cond_temp_env', cond_temp_env, .FALSE.) 265 IF(ANY(isoName == 'HTO')) & 266 CALL get_in('ok_prod_nucl_tritium', ok_prod_nucl_tritium, .FALSE., .FALSE.) 267 268 ! Ocean composition 269 CALL get_in('deltaO18_oce', deltaO18_oce, 0.0) 270 271 CALL msg('iso_O18, iso_HDO, iso_eau = '//TRIM(strStack(int2str([iso_O18, iso_HDO, iso_eau]))), modname) 272 273 !-------------------------------------------------------------- 274 ! Isotope fractionation factors and a few isotopic constants 275 !-------------------------------------------------------------- 276 ALLOCATE(tkcin0(niso)) 277 ALLOCATE(tkcin1(niso)) 278 ALLOCATE(tkcin2(niso)) 279 ALLOCATE(tnat(niso)) 280 ALLOCATE(tdifrel(niso)) 281 ALLOCATE(toce(niso)) 282 ALLOCATE(tcorr(niso)) 283 ALLOCATE(talph1(niso)) 284 ALLOCATE(talph2(niso)) 285 ALLOCATE(talph3(niso)) 286 ALLOCATE(talps1(niso)) 287 ALLOCATE(talps2(niso)) 288 ALLOCATE(alpha_liq_sol(niso)) 289 ALLOCATE(Rdefault(niso)) 290 ALLOCATE(Rmethox(niso)) 291 292 do ixt=1,niso 293 if (ixt.eq.iso_HTO) then ! Tritium 294 tkcin0(ixt) = 0.01056 295 tkcin1(ixt) = 0.0005016 296 tkcin2(ixt) = 0.0014432 297 if (tnat1) then 298 tnat(ixt)=1 299 else 300 tnat(ixt)=0. 301 endif 302 toce(ixt)=4.0E-19 ! rapport T/H = 0.2 TU Dreisigacker and Roether 1978 303 tcorr(ixt)=1. 304 tdifrel(ixt)=1./0.968 305 talph1(ixt)=46480. 306 talph2(ixt)=-103.87 307 talph3(ixt)=0. 308 talps1(ixt)=46480. 309 talps2(ixt)=-103.87 310 alpha_liq_sol(ixt)=1. 311 Rmethox(ixt)=0.0 312 endif 313 if (ixt.eq.iso_O17) then ! O17 314 pente_MWL=0.528 315 tdifrel(ixt)=1./0.98555 ! valeur utilisée en 1D et dans modèle de LdG ! tdifrel(ixt)=1./0.985452 ! donné par Amaelle 316 fac_kcin= (tdifrel(ixt)-1.0)/(tdifrel_O18-1.0) ! fac_kcin=0.5145 ! donné par Amaelle 317 tkcin0(ixt) = tkcin0_O18*fac_kcin 318 tkcin1(ixt) = tkcin1_O18*fac_kcin 319 tkcin2(ixt) = tkcin2_O18*fac_kcin 320 if (tnat1) then 321 tnat(ixt)=1 322 else 323 tnat(ixt)=0.004/100. ! O17 représente 0.004% de l'oxygène 324 endif 325 toce(ixt)=tnat(ixt)*(1.0+deltaO18_oce/1000.0)**pente_MWL 326 tcorr(ixt)=1.0+fac_enrichoce18*pente_MWL ! donné par Amaelle 327 talph1(ixt)=talph1_O18 328 talph2(ixt)=talph2_O18 329 talph3(ixt)=talph3_O18 330 talps1(ixt)=talps1_O18 331 talps2(ixt)=talps2_O18 332 alpha_liq_sol(ixt)=(alpha_liq_sol_O18)**fac_coeff_eq17_liq 333 Rdefault(ixt)=tnat(ixt)*(-3.15/1000.0+1.0) 334 Rmethox(ixt)=(230./1000.+1.)*tnat(ixt) !Zahn et al 2006 335 endif 336 if (ixt.eq.iso_O18) then ! Oxygene18 337 tkcin0(ixt) = tkcin0_O18 338 tkcin1(ixt) = tkcin1_O18 339 tkcin2(ixt) = tkcin2_O18 340 if (tnat1) then 341 tnat(ixt)=1 342 else 343 tnat(ixt)=2005.2E-6 344 endif 345 toce(ixt)=tnat(ixt)*(1.0+deltaO18_oce/1000.0) 346 tcorr(ixt)=1.0+fac_enrichoce18 347 tdifrel(ixt)=tdifrel_O18 348 talph1(ixt)=talph1_O18 349 talph2(ixt)=talph2_O18 350 talph3(ixt)=talph3_O18 351 talps1(ixt)=talps1_O18 352 talps2(ixt)=talps2_O18 353 alpha_liq_sol(ixt)=alpha_liq_sol_O18 354 Rdefault(ixt)=tnat(ixt)*(-6.0/1000.0+1.0) 355 Rmethox(ixt)=(130./1000.+1.)*tnat(ixt) !Zahn et al 2006 356 endif 357 if (ixt.eq.iso_HDO) then ! Deuterium 358 pente_MWL=8.0 359 tdifrel(ixt)=1./0.9755 ! fac_kcin=0.88 360 fac_kcin= (tdifrel(ixt)-1)/(tdifrel_O18-1) 361 tkcin0(ixt) = tkcin0_O18*fac_kcin 362 tkcin1(ixt) = tkcin1_O18*fac_kcin 363 tkcin2(ixt) = tkcin2_O18*fac_kcin 364 if (tnat1) then 365 tnat(ixt)=1 366 else 367 tnat(ixt)=155.76E-6 368 endif 369 toce(ixt)=tnat(ixt)*(1.0+pente_MWL*deltaO18_oce/1000.0) 370 tcorr(ixt)=1.0+fac_enrichoce18*pente_MWL 371 talph1(ixt)=24844. 372 talph2(ixt)=-76.248 373 talph3(ixt)=52.612E-3 374 talps1(ixt)=16288. 375 talps2(ixt)=-0.0934 376 !ZXalpha_liq_sol=1.0192 ! Weston, Ralph, 1955 377 alpha_liq_sol(ixt)=1.0212 378 ! valeur de Lehmann & Siegenthaler, 1991, Journal of 379 ! Glaciology, vol 37, p 23 380 Rdefault(ixt)=tnat(ixt)*((-6.0*pente_MWL+10.0)/1000.0+1.0) 381 Rmethox(ixt)=tnat(ixt)*(-25.0/1000.+1.) ! Zahn et al 2006 382 endif 383 if (ixt.eq.iso_eau) then ! Oxygene16 384 tkcin0(ixt) = 0.0 385 tkcin1(ixt) = 0.0 386 tkcin2(ixt) = 0.0 387 tnat(ixt)=1. 388 toce(ixt)=tnat(ixt) 389 tcorr(ixt)=1.0 390 tdifrel(ixt)=1. 391 talph1(ixt)=0. 392 talph2(ixt)=0. 393 talph3(ixt)=0. 394 talps1(ixt)=0. 395 talph3(ixt)=0. 396 alpha_liq_sol(ixt)=1. 397 Rdefault(ixt)=tnat(ixt)*1.0 398 Rmethox(ixt)=1.0 399 endif 400 enddo ! ixt=1,niso 401 402 IF(.NOT.Rdefault_smow) then 403 Rdefault(:) = 0.0 404 if (iso_eau.gt.0) Rdefault(iso_eau) = 1.0 ! correction Camille 30 mars 2023 405 ENDIF 406 write(*,*) 'Rdefault=',Rdefault 407 write(*,*) 'toce=',toce 408 409 !--- Sensitivity test: no kinetic effect in sfc evaporation 410 IF(ok_nocinsfc) THEN 411 tkcin0(1:niso) = 0.0 412 tkcin1(1:niso) = 0.0 413 tkcin2(1:niso) = 0.0 414 END IF 415 416 CALL msg('285: verif initialisation:', modname) 417 DO ixt=1,niso 418 sxt=int2str(ixt) 419 CALL msg(' * isoName('//TRIM(sxt)//') = <'//TRIM(isoName(ixt))//'>', modname) 420 CALL msg( ' tnat('//TRIM(sxt)//') = '//TRIM(real2str(tnat(ixt))), modname) 421 ! CALL msg(' alpha_liq_sol('//TRIM(sxt)//') = '//TRIM(real2str(alpha_liq_sol(ixt))), modname) 422 ! CALL msg( ' tkcin0('//TRIM(sxt)//') = '//TRIM(real2str(tkcin0(ixt))), modname) 423 ! CALL msg( ' tdifrel('//TRIM(sxt)//') = '//TRIM(real2str(tdifrel(ixt))), modname) 251 ! CALL get_in('slope_limiterxy', slope_limiterxy, 2.0) 252 ! CALL get_in('slope_limiterz', slope_limiterz, 2.0) 253 CALL get_in('modif_ratqs', modif_ratqs, 0) 254 CALL get_in('Pcrit_ratqs', Pcrit_ratqs, 500.0) 255 CALL get_in('ratqsbasnew', ratqsbasnew, 0.05) 256 CALL get_in('fac_modif_evaoce', fac_modif_evaoce, 1.0) 257 CALL get_in('ok_bidouille_wake', ok_bidouille_wake, 0) 258 ! si oui, la temperature de cond est celle de l'environnement, pour eviter 259 ! bugs quand temperature dans ascendances convs est mal calculee 260 CALL get_in('cond_temp_env', cond_temp_env, .FALSE.) 261 IF(ANY(isoName == 'HTO')) & 262 CALL get_in('ok_prod_nucl_tritium', ok_prod_nucl_tritium, .FALSE., .FALSE.) 263 CALL get_in('tnateq1', ltnat1, .TRUE.) 264 265 CALL msg('iso_O18, iso_HDO, iso_eau = '//TRIM(strStack(int2str([iso_O18, iso_HDO, iso_eau]))), modname) 266 267 !-------------------------------------------------------------- 268 ! Parameters that depend on the nature of water isotopes: 269 !-------------------------------------------------------------- 270 ALLOCATE(tnat (niso), talph1(niso), talps1(niso), tkcin0(niso), tdifrel (niso), alpha (niso)) 271 ALLOCATE(toce (niso), talph2(niso), talps2(niso), tkcin1(niso), Rdefault(niso), alpha_liq_sol(niso)) 272 ALLOCATE(tcorr(niso), talph3(niso), tkcin2(niso), Rmethox (niso)) 273 274 !=== H216O 275 is = iso_eau 276 IF(is /= 0) THEN 277 tdifrel (is) = 1.0 278 alpha (is) = alpha_ideal_H216O 279 tnat (is) = tnat_H216O; IF(ltnat1) tnat(is) = 1.0 280 toce (is) = tnat(is) 281 tcorr (is) = 1.0 282 talph1 (is) = 0.0; talps1(is) = 0.0; tkcin0(is) = 0.0 283 talph2 (is) = 0.0; talps2(is) = 0.0; tkcin1(is) = 0.0 284 talph3 (is) = 0.0; tkcin2(is) = 0.0 285 Rdefault(is) = tnat(is)*1.0 286 Rmethox (is) = 1.0 287 alpha_liq_sol(is) = 1.0 288 END IF 289 290 !=== H217O 291 is = iso_O17 292 IF(is /= 0) THEN; pente_MWL = 0.528 293 tdifrel (is) = 1./0.98555 ! used in 1D and in LdG model ; tdifrel=1./0.985452: from Amaelle 294 alpha (is) = alpha_ideal_H217O 295 tnat (is) = tnat_H217O; IF(ltnat1) tnat(is) = 1.0 296 toce (is) = tnat(is)*(1.0+deltaO18_oce/1000.0)**pente_MWL 297 tcorr (is) = 1.0+fac_enrichoce18*pente_MWL 298 fac_kcin = (tdifrel(is)-1.0)/(tdifrel_O18-1.0) ! fac_kcin=0.5145: from Amaelle 299 talph1 (is) = talph1_O18; talps1(is) = talps1_O18; tkcin0(is) = tkcin0_O18*fac_kcin 300 talph2 (is) = talph2_O18; talps2(is) = talps2_O18; tkcin1(is) = tkcin1_O18*fac_kcin 301 talph3 (is) = talph3_O18; tkcin2(is) = tkcin2_O18*fac_kcin 302 Rdefault(is) = tnat(is)*(1.0-3.15/1000.) 303 Rmethox (is) = tnat(is)*(1.0+230./1000.) 304 alpha_liq_sol(is) = alpha_liq_sol_O18**fac_coeff_eq17_liq 305 END IF 306 307 !=== H218O 308 is = iso_O18 309 IF(is /= 0) THEN 310 tdifrel (is) = tdifrel_O18 311 alpha (is) = alpha_ideal_H218O 312 tnat (is) = tnat_H218O; IF(ltnat1) tnat(is) = 1.0 313 toce (is) = tnat(is)*(1.0+deltaO18_oce/1000.0) 314 tcorr (is) = 1.0+fac_enrichoce18 315 talph1 (is) = talph1_O18; talps1(is) = talps1_O18; tkcin0(is) = tkcin0_O18 316 talph2 (is) = talph2_O18; talps2(is) = talps2_O18; tkcin1(is) = tkcin1_O18 317 talph3 (is) = talph3_O18; tkcin2(is) = tkcin2_O18 318 Rdefault(is) = tnat(is)*(1.0-6.00/1000.) 319 Rmethox (is) = tnat(is)*(1.0+130./1000.) ! Zahn & al. 2006 320 alpha_liq_sol(is) = alpha_liq_sol_O18 321 END IF 322 323 !=== HDO 324 is = iso_HDO 325 IF(is /= 0) THEN; pente_MWL = 8.0 326 tdifrel (is) = 1./0.9755 ! fac_kcin=0.88 327 alpha (is) = alpha_ideal_HDO 328 tnat (is) = tnat_HDO; IF(ltnat1) tnat(is) = 1.0 329 toce (is) = tnat(is)*(1.0+deltaO18_oce/1000.0*pente_MWL) 330 tcorr (is) = 1.0+fac_enrichoce18*pente_MWL 331 fac_kcin = (tdifrel(is)-1.0)/(tdifrel_O18-1.0) 332 talph1 (is) = 24844.; talps1(is) = 16288.; tkcin0(is) = tkcin0_O18*fac_kcin 333 talph2 (is) = -76.248; talps2(is) = -0.0934; tkcin1(is) = tkcin1_O18*fac_kcin 334 talph3 (is) = 52.612E-3; tkcin2(is) = tkcin2_O18*fac_kcin 335 Rdefault(is) = tnat(is)*(1.0+(10.0-6.0*pente_MWL)/1000.) 336 Rmethox (is) = tnat(is)*(1.0-25.0/1000.) 337 alpha_liq_sol(is) = 1.0212 ! Lehmann & Siegenthaler, 1991, Jo. of Glaciology, vol 37, p 23 338 ! alpha_liq_sol=1.0192: Weston, Ralph, 1955 339 END IF 340 341 !=== HTO 342 is = iso_HTO 343 IF(is /= 0) THEN 344 tdifrel (is) = 1./0.968 345 alpha (is) = alpha_ideal_HTO 346 tnat (is) = tnat_HTO; IF(ltnat1) tnat(is) = 1.0 347 toce (is) = 4.0E-19 ! ratio T/H = 0.2 TU Dreisigacker & Roether 1978 348 tcorr (is) = 1.0 349 talph1 (is) = 46480.; talps1(is) = 46480.; tkcin0(is) = 0.01056 350 talph2 (is) = -103.87; talps2(is) = -103.87; tkcin1(is) = 0.0005016 351 talph3 (is) = 0.0; tkcin2(is) = 0.0014432 352 Rdefault(is) = 0.0 353 Rmethox (is) = 0.0 354 alpha_liq_sol(is) = 1.0 355 END IF 356 357 IF(.NOT. Rdefault_smow) THEN 358 Rdefault(:) = 0.0; IF(iso_eau > 0) Rdefault(iso_eau) = 1.0 359 END IF 360 WRITE(*,*) 'Rdefault = ',Rdefault 361 WRITE(*,*) 'toce = ', toce 362 363 !--- Sensitivity test: no kinetic effect in sfc evaporation 364 IF(ok_nocinsfc) THEN 365 tkcin0(1:niso) = 0.0 366 tkcin1(1:niso) = 0.0 367 tkcin2(1:niso) = 0.0 368 END IF 369 370 CALL msg('285: verif initialisation:', modname) 371 DO ixt=1,niso 372 sxt=int2str(ixt) 373 CALL msg(' * isoName('//TRIM(sxt)//') = <'//TRIM(isoName(ixt))//'>', modname) 374 CALL msg( ' tnat('//TRIM(sxt)//') = '//TRIM(real2str(tnat(ixt))), modname) 375 ! CALL msg(' alpha_liq_sol('//TRIM(sxt)//') = '//TRIM(real2str(alpha_liq_sol(ixt))), modname) 376 ! CALL msg( ' tkcin0('//TRIM(sxt)//') = '//TRIM(real2str(tkcin0(ixt))), modname) 377 ! CALL msg( ' tdifrel('//TRIM(sxt)//') = '//TRIM(real2str(tdifrel(ixt))), modname) 378 END DO 379 CALL msg('69: lambda = '//TRIM(real2str(lambda_sursat)), modname) 380 CALL msg('69: thumxt1 = '//TRIM(real2str(thumxt1)), modname) 381 CALL msg('69: h_land_ice = '//TRIM(real2str(h_land_ice)), modname) 382 CALL msg('69: P_veg = '//TRIM(real2str(P_veg)), modname) 383 !============================================================================================================================== 384 ELSE 385 !============================================================================================================================== 386 CALL abort_physic('"isotopes_mod" is not set up yet for isotopes family "'//TRIM(isoFamilies(ii))//'"', modname, 1) 387 !============================================================================================================================== 388 END IF 389 !============================================================================================================================== 424 390 END DO 425 CALL msg('69: lambda = '//TRIM(real2str(lambda_sursat)), modname)426 CALL msg('69: thumxt1 = '//TRIM(real2str(thumxt1)), modname)427 CALL msg('69: h_land_ice = '//TRIM(real2str(h_land_ice)), modname)428 CALL msg('69: P_veg = '//TRIM(real2str(P_veg)), modname)429 391 430 392 END SUBROUTINE iso_init -
LMDZ6/trunk/libf/phylmdiso/isotopes_routines_mod.F90
r5084 r5183 16419 16419 USE isotopes_mod, ONLY: isoName,iso_HDO,iso_eau 16420 16420 USE phyetat0_get_mod, ONLY: phyetat0_get, phyetat0_srf 16421 USE readTracFiles_mod,ONLY: new2oldH2O16422 USE strings_mod, ONLY: strIdx, str Tail, maxlen, msg, int2str16421 USE infotrac_phy, ONLY: new2oldH2O 16422 USE strings_mod, ONLY: strIdx, strHead, strTail, maxlen, msg, int2str 16423 16423 #ifdef ISOVERIF 16424 16424 USE isotopes_verif_mod … … 16459 16459 outiso = isoName(ixt) 16460 16460 oldIso = strTail(new2oldH2O(outiso), '_') !--- Remove "H2O_" from "H2O_<iso>[_<tag>]" 16461 i = INDEX(outiso, '_', .TRUE.) 16462 oldIso2 = outiso(1:i-1)//outiso(i+1:LEN_TRIM(outiso)) ! CR 2023: on ajoute cette possibilité aussi, elle correspond au cas le plus récent. 16461 oldIso2= TRIM(strHead(outiso,'_'))//strTail(outiso,'_') ! CR 2023: most recent possibility 16463 16462 ! write(*,*) 'tmp 16541:' 16464 16463 ! write(*,*) 'outiso=',outiso -
LMDZ6/trunk/libf/phylmdiso/isotrac_mod.F90
r4493 r5183 3 3 4 4 MODULE isotrac_mod 5 USE infotrac_phy, ONLY: niso, ntiso, nzone 6 USE readTracFiles_mod, ONLY: delPhase 7 USE isotopes_mod, ONLY: ridicule, get_in 5 USE infotrac_phy, ONLY: niso, ntiso, nzone, delPhase 6 USE isotopes_mod, ONLY: ridicule, get_in 8 7 9 8 IMPLICIT NONE -
LMDZ6/trunk/libf/phylmdiso/phyetat0_mod.F90
r5084 r5183 40 40 USE geometry_mod, ONLY: longitude_deg, latitude_deg 41 41 USE iostart, ONLY: close_startphy, get_field, get_var, open_startphy 42 USE infotrac_phy, ONLY: nqtot, nbtr, type_trac, tracers 43 USE readTracFiles_mod,ONLY: maxlen, new2oldH2O42 USE infotrac_phy, ONLY: nqtot, nbtr, type_trac, tracers, new2oldH2O 43 USE strings_mod, ONLY: maxlen 44 44 USE traclmdz_mod, ONLY: traclmdz_from_restart 45 45 USE carbon_cycle_mod, ONLY: carbon_cycle_init, carbon_cycle_cpl, carbon_cycle_tr, carbon_cycle_rad, co2_send, RCO2_glo -
LMDZ6/trunk/libf/phylmdiso/physiq_mod.F90
r5169 r5183 39 39 USE ioipsl_getin_p_mod, ONLY : getin_p 40 40 USE indice_sol_mod 41 USE infotrac_phy, ONLY: nqtot, nbtr, nqo, tracers, type_trac,ivap,iliq,isol 42 USE readTracFiles_mod, ONLY: addPhase 41 USE infotrac_phy, ONLY: nqtot, nbtr, nqo, tracers, type_trac,addPhase, ivap, iliq, isol 43 42 USE strings_mod, ONLY: strIdx 44 43 USE iophy
Note: See TracChangeset
for help on using the changeset viewer.