Changeset 5202 for LMDZ6/branches/cirrus/libf/misc
- Timestamp:
- Sep 20, 2024, 12:32:04 PM (4 months ago)
- Location:
- LMDZ6/branches/cirrus
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
LMDZ6/branches/cirrus
- Property svn:mergeinfo changed
-
LMDZ6/branches/cirrus/libf/misc/readTracFiles_mod.f90
r4951 r5202 1 1 MODULE readTracFiles_mod 2 2 3 USE strings_mod, ONLY: msg, find, get_in, str2int, dispTable, strHead, strReduce, strFind, strStack, strIdx, & 4 test, removeComment, cat, fmsg, maxlen, int2str, checkList, strParse, strReplace, strTail, strCount, reduceExpr 3 USE strings_mod, ONLY: msg, find, get_in, dispTable, strHead, strReduce, strFind, strStack, strIdx, & 4 removeComment, cat, fmsg, maxlen, checkList, strParse, strReplace, strTail, strCount, reduceExpr, & 5 int2str, str2int, real2str, str2real, bool2str, str2bool 5 6 6 7 IMPLICIT NONE … … 9 10 10 11 PUBLIC :: maxlen !--- PARAMETER FOR CASUAL STRING LENGTH 11 PUBLIC :: tracers !--- TRACERS DESCRIPTION DATABASE 12 PUBLIC :: trac_type, setGeneration, indexUpdate !--- TRACERS DESCRIPTION ASSOCIATED TOOLS 12 PUBLIC :: trac_type, tracers, setGeneration, indexUpdate !--- TRACERS DESCRIPTION DATABASE + ASSOCIATED TOOLS 13 13 PUBLIC :: testTracersFiles, readTracersFiles !--- TRACERS FILES READING ROUTINES 14 PUBLIC :: getKey , fGetKey, fGetKeys, addKey, setDirectKeys !--- TOOLS TO GET/SET KEYS FROM/TO tracers & isotopes15 PUBLIC :: getKeysDBase, setKeysDBase !--- TOOLS TO GET/SET THE DATABASE (tracers & isotopes)16 17 PUBLIC :: addPhase, getiPhase, old_phases, phases_sep, &!--- FUNCTIONS RELATED TO THE PHASES18 nphases, delPhase, getPhase, known_phases, phases_names!--- + ASSOCIATED VARIABLES14 PUBLIC :: getKeysDBase, setKeysDBase !--- TOOLS TO GET/SET THE DATABASE (tracers & isotopes) 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 & isotopes 17 PUBLIC :: addPhase, delPhase, getPhase, getiPhase, & !--- FUNCTIONS RELATED TO THE PHASES 18 nphases, old_phases, phases_sep, known_phases, phases_names !--- + ASSOCIATED VARIABLES 19 19 20 20 PUBLIC :: oldH2OIso, newH2OIso, old2newH2O, new2oldH2O !--- H2O ISOTOPES BACKWARD COMPATIBILITY (OLD traceur.def) 21 21 PUBLIC :: oldHNO3, newHNO3 !--- HNO3 REPRO BACKWARD COMPATIBILITY (OLD start.nc) 22 22 23 PUBLIC :: tran0 , idxAncestor, ancestor !--- GENERATION 0 TRACER + TOOLS FOR GENERATIONS23 PUBLIC :: tran0 !--- TRANSPORTING FLUID (USUALLY air) 24 24 25 25 !=== FOR ISOTOPES: GENERAL 26 PUBLIC :: isot_type, readIsotopesFile, isoSelect !--- ISOTOPES DESCRIPTION TYPE + READING ROUTINE 27 PUBLIC :: ixIso, nbIso !--- INDEX OF SELECTED ISOTOPES CLASS + NUMBER OF CLASSES 26 PUBLIC :: isot_type, processIsotopes, isoSelect, ixIso, nbIso !--- PROCESS [AND READ] & SELECT ISOTOPES + CLASS IDX & NUMBER 28 27 29 28 !=== FOR ISOTOPES: H2O FAMILY ONLY … … 36 35 PUBLIC :: itZonIso !--- Idx IN isoName(1:niso) = f(tagging idx, isotope idx) 37 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 first 38 38 PUBLIC :: isoCheck !--- FLAG TO RUN ISOTOPES CHECKING ROUTINES 39 39 40 40 PUBLIC :: maxTableWidth 41 41 !------------------------------------------------------------------------------------------------------------------------------ 42 TYPE :: keys_type !=== TYPE FOR A SET OF KEYS ASSOCIATED TO AN ELEMENT43 CHARACTER(LEN=maxlen) :: name !--- Tracer name44 CHARACTER(LEN=maxlen), ALLOCATABLE :: key(:) !--- Keys string list45 CHARACTER(LEN=maxlen), ALLOCATABLE :: val(:) !--- Corresponding values string list42 TYPE :: keys_type !=== TYPE FOR A SET OF KEYS ASSOCIATED TO AN ELEMENT 43 CHARACTER(LEN=maxlen) :: name !--- Tracer name 44 CHARACTER(LEN=maxlen), ALLOCATABLE :: key(:) !--- Keys string list 45 CHARACTER(LEN=maxlen), ALLOCATABLE :: val(:) !--- Corresponding values string list 46 46 END TYPE keys_type 47 47 !------------------------------------------------------------------------------------------------------------------------------ 48 TYPE :: trac_type !=== TYPE FOR A SINGLE TRACER NAMED "name"49 CHARACTER(LEN=maxlen) :: name = '' !--- Name of the tracer50 CHARACTER(LEN=maxlen) :: gen0Name = '' !--- First generation ancestor name51 CHARACTER(LEN=maxlen) :: parent = '' !--- Parentname52 CHARACTER(LEN=maxlen) :: longName = '' !--- Long name (with advection scheme suffix)53 CHARACTER(LEN=maxlen) :: type = 'tracer' !--- Type (so far: 'tracer' / 'tag')54 CHARACTER(LEN=maxlen) :: phase = 'g' !--- Phase ('g'as / 'l'iquid / 's'olid)55 CHARACTER(LEN=maxlen) :: component = '' !--- Coma-separated list of components (Ex: lmdz,inca)56 INTEGER :: iGeneration = -1 !--- Generation number (>=0)57 INTEGER :: i qParent = 0 !--- Parent index58 INTEGER , ALLOCATABLE :: iqDescen(:) !--- Descendants index (in growing generation order)59 INTEGER :: nqDescen = 0 !--- Number of descendants (all generations)60 INTEGER :: nq Children = 0 !--- Number of children (first generation)61 TYPE(keys_type) :: keys !--- <key>=<val> pairs vector62 INTEGER :: iadv = 10 !--- Advection scheme used63 LOGICAL :: isAdvected = .FALSE. !--- "true" tracers: iadv > 0. COUNT(isAdvected )=nqtrue64 LOGICAL :: isInPhysics = .TRUE. !--- "true" tracers: in tr_seri. COUNT(isInPhysics)=nqtottr65 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)%phase48 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 69 END TYPE trac_type 70 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)73 LOGICAL :: check=.FALSE. !--- Triggering of the checking routines74 TYPE(keys_type), ALLOCATABLE :: keys(:) !--- Isotopes keys/values pairs list (length: niso)75 CHARACTER(LEN=maxlen), ALLOCATABLE :: trac(:) !--- Isotopes + tagging tracers list (length: ntiso)76 CHARACTER(LEN=maxlen), ALLOCATABLE :: zone(:) !--- Geographic tagging zones names list (length: nzone)77 CHARACTER(LEN=maxlen) :: phase = 'g' !--- Phases list: [g][l][s] (length: nphas)78 INTEGER :: niso = 0 !--- Number of isotopes, excluding tagging tracers79 INTEGER :: n zone = 0 !--- Number of geographic tagging zones80 INTEGER :: n tiso = 0 !--- Number of isotopes, including tagging tracers81 INTEGER :: nphas = 0 !--- Numberphases82 INTEGER, ALLOCATABLE :: iqIsoPha(:,:) !--- Idx in "tracers(1:nqtot)" = f(name(1:ntiso)),phas)83 !--- "iqIsoPha"former name: "iqiso"84 INTEGER, ALLOCATABLE :: i tZonIso(:,:) !--- Idx in "trac(1:ntiso)" = f(zone, name(1:niso))85 !--- "itZonIso" former name: "index_trac"86 END TYPE isot_type 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) 73 TYPE(keys_type), ALLOCATABLE :: keys(:) !--- Isotopes keys/values pairs list (length: niso) 74 LOGICAL :: check=.FALSE. !--- Flag for checking routines triggering 75 CHARACTER(LEN=maxlen), ALLOCATABLE :: trac(:) !--- Isotopes + tagging tracers list (length: ntiso) 76 CHARACTER(LEN=maxlen), ALLOCATABLE :: zone(:) !--- Geographic tagging zones names list (length: nzone) 77 CHARACTER(LEN=maxlen) :: phase = 'g' !--- Phases list: [g][l][s] (length: nphas) 78 INTEGER :: niso = 0 !--- Number of isotopes, excluding tagging tracers 79 INTEGER :: ntiso = 0 !--- Number of isotopes, including tagging tracers 80 INTEGER :: nzone = 0 !--- Number of geographic tagging zones 81 INTEGER :: nphas = 0 !--- Number of phases 82 INTEGER, ALLOCATABLE :: iqIsoPha(:,:) !--- Idx in "tracers(1:nqtot)" = f(name(1:ntiso),phas) 83 !--- (former name: "iqiso" 84 INTEGER, ALLOCATABLE :: iqWIsoPha(:,:) !--- Idx in "tracers(1:nqtot)" = f([H2O,name(1:ntiso)],phas) 85 INTEGER, ALLOCATABLE :: itZonIso(:,:) !--- Idx in "trac(1:ntiso)" = f(zone, name(1:niso)) 86 END TYPE isot_type !--- (former name: "index_trac") 87 87 !------------------------------------------------------------------------------------------------------------------------------ 88 88 TYPE :: dataBase_type !=== TYPE FOR TRACERS SECTION 89 CHARACTER(LEN=maxlen) :: name!--- Section name89 CHARACTER(LEN=maxlen) :: name !--- Section name 90 90 TYPE(trac_type), ALLOCATABLE :: trac(:) !--- Tracers descriptors 91 91 END TYPE dataBase_type 92 92 !------------------------------------------------------------------------------------------------------------------------------ 93 93 INTERFACE getKey 94 MODULE PROCEDURE getKeyByName_s1, getKeyByName_s1m, getKeyByName_sm, getKey_sm, & 95 getKeyByName_i1, getKeyByName_i1m, getKeyByName_im, getKey_im, & 96 getKeyByName_r1, getKeyByName_r1m, getKeyByName_rm, getKey_rm, & 97 getKeyByName_l1, getKeyByName_l1m, getKeyByName_lm, getKey_lm 94 MODULE PROCEDURE & 95 getKeyByIndex_s111, getKeyByIndex_sm11, getKeyByIndex_s1m1, getKeyByIndex_smm1, getKeyByIndex_s1mm, getKeyByIndex_smmm, & 96 getKeyByIndex_i111, getKeyByIndex_im11, getKeyByIndex_i1m1, getKeyByIndex_imm1, getKeyByIndex_i1mm, getKeyByIndex_immm, & 97 getKeyByIndex_r111, getKeyByIndex_rm11, getKeyByIndex_r1m1, getKeyByIndex_rmm1, getKeyByIndex_r1mm, getKeyByIndex_rmmm, & 98 getKeyByIndex_l111, getKeyByIndex_lm11, getKeyByIndex_l1m1, getKeyByIndex_lmm1, getKeyByIndex_l1mm, getKeyByIndex_lmmm, & 99 getKeyByName_s111, getKeyByName_sm11, getKeyByName_s1m1, getKeyByName_smm1, getKeyByName_s1mm, getKeyByName_smmm, & 100 getKeyByName_i111, getKeyByName_im11, getKeyByName_i1m1, getKeyByName_imm1, getKeyByName_i1mm, getKeyByName_immm, & 101 getKeyByName_r111, getKeyByName_rm11, getKeyByName_r1m1, getKeyByName_rmm1, getKeyByName_r1mm, getKeyByName_rmmm, & 102 getKeyByName_l111, getKeyByName_lm11, getKeyByName_l1m1, getKeyByName_lmm1, getKeyByName_l1mm, getKeyByName_lmmm 98 103 END INTERFACE getKey 99 104 !------------------------------------------------------------------------------------------------------------------------------ 100 INTERFACE isoSelect; MODULE PROCEDURE isoSelectByIndex, isoSelectByName; END INTERFACE isoSelect 101 INTERFACE old2newH2O; MODULE PROCEDURE old2newH2O_1, old2newH2O_m; END INTERFACE old2newH2O 102 INTERFACE new2oldH2O; MODULE PROCEDURE new2oldH2O_1, new2oldH2O_m; END INTERFACE new2oldH2O 103 INTERFACE fGetKey; MODULE PROCEDURE fgetKeyIdx_s1, fgetKeyNam_s1; END INTERFACE fGetKey 104 INTERFACE tracersSubset; MODULE PROCEDURE trSubset_Indx, trSubset_Name, trSubset_gen0Name; END INTERFACE tracersSubset 105 INTERFACE idxAncestor; MODULE PROCEDURE idxAncestor_1, idxAncestor_m, idxAncestor_mt; END INTERFACE idxAncestor 106 INTERFACE ancestor; MODULE PROCEDURE ancestor_1, ancestor_m, ancestor_mt; END INTERFACE ancestor 107 INTERFACE addKey; MODULE PROCEDURE addKey_1; END INTERFACE addKey!, addKey_m, addKey_mm; END INTERFACE addKey 108 INTERFACE addPhase; MODULE PROCEDURE addPhase_s1, addPhase_sm, addPhase_i1, addPhase_im; END INTERFACE addPhase 105 INTERFACE addKey 106 MODULE PROCEDURE addKey_s11, addKey_s1m, addKey_smm, addKey_i11, addKey_i1m, addKey_imm, & 107 addKey_r11, addKey_r1m, addKey_rmm, addKey_l11, addKey_l1m, addKey_lmm 108 END INTERFACE addKey 109 !------------------------------------------------------------------------------------------------------------------------------ 110 INTERFACE isoSelect; MODULE PROCEDURE isoSelectByIndex, isoSelectByName; END INTERFACE isoSelect 111 INTERFACE old2newH2O; MODULE PROCEDURE old2newH2O_1, old2newH2O_m; END INTERFACE old2newH2O 112 INTERFACE new2oldH2O; MODULE PROCEDURE new2oldH2O_1, new2oldH2O_m; END INTERFACE new2oldH2O 113 INTERFACE addTracer; MODULE PROCEDURE addTracer_1, addTracer_1def; END INTERFACE addTracer 114 INTERFACE delTracer; MODULE PROCEDURE delTracer_1, delTracer_1def; END INTERFACE delTracer 115 INTERFACE addPhase; MODULE PROCEDURE addPhase_s1, addPhase_sm, addPhase_i1, addPhase_im; END INTERFACE addPhase 116 INTERFACE tracersSubset; MODULE PROCEDURE trSubset_Indx, trSubset_Name, trSubset_gen0Name; END INTERFACE tracersSubset 109 117 !------------------------------------------------------------------------------------------------------------------------------ 110 118 … … 114 122 !--- SOME PARAMETERS THAT ARE NOT LIKELY TO CHANGE OFTEN 115 123 CHARACTER(LEN=maxlen), SAVE :: tran0 = 'air' !--- Default transporting fluid 116 CHARACTER(LEN=maxlen), PARAMETER :: old_phases = 'vli fbc'!--- Old phases for water (no separator)117 CHARACTER(LEN=maxlen), PARAMETER :: known_phases = 'gls fbc'!--- Known phases initials124 CHARACTER(LEN=maxlen), PARAMETER :: old_phases = 'vlirb' !--- Old phases for water (no separator) 125 CHARACTER(LEN=maxlen), PARAMETER :: known_phases = 'glsrb' !--- Known phases initials 118 126 INTEGER, PARAMETER :: nphases = LEN_TRIM(known_phases) !--- Number of phases 119 127 CHARACTER(LEN=maxlen), SAVE :: phases_names(nphases) & !--- Known phases names 120 = ['gaseous', 'liquid ', 'solid ', 'fracld ', 'blosnow', 'cldvapr'] 121 CHARACTER(LEN=1), SAVE :: phases_sep = '_' !--- Phase separator 122 LOGICAL, SAVE :: tracs_merge = .TRUE. !--- Merge/stack tracers lists 123 LOGICAL, SAVE :: lSortByGen = .TRUE. !--- Sort by growing generation 128 = ['gaseous ', 'liquid ', 'solid ', 'cloud ','blownSnow'] 129 CHARACTER(LEN=1), SAVE :: phases_sep = '_' !--- Phase separator 124 130 CHARACTER(LEN=maxlen), SAVE :: isoFile = 'isotopes_params.def'!--- Name of the isotopes parameters file 125 131 … … 128 134 CHARACTER(LEN=maxlen), SAVE :: newH2OIso(5) = ['H216O', 'HDO ', 'H218O', 'H217O', 'HTO '] 129 135 130 !--- CORRESPONDANCE BETWEEN OLD AND NEW HNO3 RELATED SPECIES NAMES 136 !--- CORRESPONDANCE BETWEEN OLD AND NEW HNO3 RELATED SPECIES NAMES (FOR REPROBUS) 131 137 CHARACTER(LEN=maxlen), SAVE :: oldHNO3(2) = ['HNO3_g ', 'HNO3 '] 132 138 CHARACTER(LEN=maxlen), SAVE :: newHNO3(2) = ['HNO3 ', 'HNO3tot'] … … 138 144 !=== ALIASES OF VARIABLES FROM SELECTED ISOTOPES FAMILY EMBEDDED IN "isotope" (isotopes(ixIso)) 139 145 TYPE(isot_type), SAVE, POINTER :: isotope !--- CURRENTLY SELECTED ISOTOPES FAMILY DESCRIPTOR 140 INTEGER, SAVE :: ixIso, iH2O 146 INTEGER, SAVE :: ixIso, iH2O=0 !--- Index of the selected isotopes family and H2O family 141 147 INTEGER, SAVE :: nbIso !--- Number of isotopes classes 142 148 LOGICAL, SAVE :: isoCheck !--- Flag to trigger the checking routines … … 148 154 nphas, ntiso !--- NUMBER OF PHASES AND ISOTOPES + ISOTOPIC TAGGING TRACERS 149 155 INTEGER, SAVE, POINTER ::itZonIso(:,:), & !--- INDEX IN "isoTrac" AS f(tagging zone idx, isotope idx) 150 iqIsoPha(:,:) !--- INDEX IN "qx" AS f(isotopic tracer idx, phase idx) 156 iqIsoPha(:,:), & !--- INDEX IN "qx" AS f(isotopic tracer idx, phase idx) 157 iqWIsoPha(:,:) !--- INDEX IN "qx" AS f(H2O + isotopic tracer idx, phase idx) 158 159 !=== PARAMETERS FOR DEFAULT BEHAVIOUR 160 LOGICAL, PARAMETER :: lTracsMerge = .FALSE. !--- Merge/stack tracers lists 161 LOGICAL, PARAMETER :: lSortByGen = .TRUE. !--- Sort by growing generation 151 162 152 163 INTEGER, PARAMETER :: maxTableWidth = 192 !--- Maximum width of a table displayed with "dispTable" … … 179 190 ! * If you need to convert a %key/%val pair into a direct-access key, add the corresponding line in "setDirectKeys". 180 191 !============================================================================================================================== 181 LOGICAL FUNCTION readTracersFiles(type_trac, lRepr) RESULT(lerr) 182 !------------------------------------------------------------------------------------------------------------------------------ 183 CHARACTER(LEN=*), INTENT(IN) :: type_trac !--- List of components used 184 LOGICAL, OPTIONAL, INTENT(IN) :: lRepr !--- Activate the HNNO3 exceptions for REPROBUS 192 LOGICAL FUNCTION readTracersFiles(type_trac, tracs, lRepr) RESULT(lerr) 193 !------------------------------------------------------------------------------------------------------------------------------ 194 CHARACTER(LEN=*), INTENT(IN) :: type_trac !--- List of components used 195 TYPE(trac_type), ALLOCATABLE, TARGET, OPTIONAL, INTENT(OUT) :: tracs(:) !--- Tracers descriptor for external storage 196 LOGICAL, OPTIONAL, INTENT(IN) :: lRepr !--- Activate the HNO3 exceptions for REPROBUS 185 197 CHARACTER(LEN=maxlen), ALLOCATABLE :: s(:), sections(:), trac_files(:) 186 198 CHARACTER(LEN=maxlen) :: str, fname, tname, pname, cname 187 199 INTEGER :: nsec, ierr, it, ntrac, ns, ip, ix, fType 200 INTEGER, ALLOCATABLE :: iGen(:) 188 201 LOGICAL :: lRep 189 202 TYPE(keys_type), POINTER :: k … … 195 208 196 209 !--- Required sections + corresponding files names (new style single section case) for tests 197 IF(test(testTracersFiles(modname, type_trac, fType, .FALSE., trac_files, sections), lerr)) RETURN210 lerr = testTracersFiles(modname, type_trac, fType, .FALSE., trac_files, sections); IF(lerr) RETURN 198 211 nsec = SIZE(sections) 199 212 200 213 !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 201 SELECT CASE(fType) !--- Set %name, %genOName, %parent, %type, %phase, %component, %iGeneration, %keys214 SELECT CASE(fType) !--- Set name, component, parent, phase, iGeneration, gen0Name, type 202 215 !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 203 216 CASE(1) !=== OLD FORMAT "traceur.def" 204 217 !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 205 218 !--- OPEN THE "traceur.def" FILE 206 OPEN(90, FILE="traceur.def", FORM='formatted', STATUS='old', IOSTAT=ierr)219 OPEN(90, FILE="traceur.def", FORM='formatted', STATUS='old', POSITION='REWIND', IOSTAT=ierr) 207 220 208 221 !--- GET THE TRACERS NUMBER 209 222 READ(90,'(i3)',IOSTAT=ierr)ntrac !--- Number of lines/tracers 210 IF(test(fmsg('Invalid format for "'//TRIM(fname)//'"', modname, ierr /= 0), lerr)) RETURN223 lerr = ierr/=0; IF(fmsg('Invalid format for "'//TRIM(fname)//'"', modname, lerr)) RETURN 211 224 212 225 !--- READ THE REMAINING LINES: <hadv> <vadv> <tracer> [<transporting fluid>] 213 IF(ALLOCATED(tracers)) DEALLOCATE(tracers)214 226 ALLOCATE(tracers(ntrac)) 215 DO it =1,ntrac!=== READ RAW DATA: loop on the line/tracer number227 DO it = 1, ntrac !=== READ RAW DATA: loop on the line/tracer number 216 228 READ(90,'(a)',IOSTAT=ierr) str 217 IF(test(fmsg('Invalid format for "' //TRIM(fname)//'"', modname, ierr>0), lerr)) RETURN218 IF(test(fmsg('Not enough lines in "'//TRIM(fname)//'"', modname, ierr<0), lerr)) RETURN229 lerr = ierr>0; IF(fmsg('Invalid format for "' //TRIM(fname)//'"', modname, lerr)) RETURN 230 lerr = ierr<0; IF(fmsg('Not enough lines in "'//TRIM(fname)//'"', modname, lerr)) RETURN 219 231 lerr = strParse(str, ' ', s, ns) 220 232 CALL msg('This file is for air tracers only', modname, ns == 3 .AND. it == 1) … … 226 238 ix = strIdx(oldHNO3, s(3)) 227 239 IF(ix /= 0 .AND. lRep) tname = newHNO3(ix) !--- Exception for HNO3 (REPROBUS ONLY) 228 tracers(it)%name = tname !--- Set %name229 CALL addKey _1('name', tname, k)!--- Set the name of the tracer240 tracers(it)%name = tname !--- Set the name of the tracer 241 CALL addKey('name', tname, k) !--- Set the name of the tracer 230 242 tracers(it)%keys%name = tname !--- Copy tracers names in keys components 231 243 … … 233 245 cname = type_trac !--- Name of the model component 234 246 IF(ANY([(addPhase('H2O', ip), ip = 1, nphases)] == tname)) cname = 'lmdz' 235 tracers(it)%component = cname !--- Set %component236 CALL addKey _1('component', cname, k)!--- Set the name of the model component247 tracers(it)%component = cname !--- Set component 248 CALL addKey('component', cname, k) !--- Set the name of the model component 237 249 238 250 !=== NAME OF THE PARENT … … 243 255 IF(ix /= 0 .AND. lRep) pname = newHNO3(ix) !--- Exception for HNO3 (REPROBUS ONLY) 244 256 END IF 245 tracers(it)%parent = pname !--- Set %parent246 CALL addKey _1('parent', pname, k)257 tracers(it)%parent = pname !--- Set the parent name 258 CALL addKey('parent', pname, k) 247 259 248 260 !=== PHASE AND ADVECTION SCHEMES NUMBERS 249 tracers(it)%phase = known_phases(ip:ip) !--- Set %phase: tracer phase(default: "g"azeous)250 CALL addKey _1('phase', known_phases(ip:ip), k) !--- Set the phaseof the tracer (default: "g"azeous)251 CALL addKey _1('hadv', s(1), k)!--- Set the horizontal advection schemes number252 CALL addKey _1('vadv', s(2), k)!--- Set the vertical advection schemes number261 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) 263 CALL addKey('hadv', s(1), k) !--- Set the horizontal advection schemes number 264 CALL addKey('vadv', s(2), k) !--- Set the vertical advection schemes number 253 265 END DO 254 266 CLOSE(90) 255 IF(test(setGeneration(tracers), lerr)) RETURN !--- Set %iGeneration and %gen0Name 256 WHERE(tracers%iGeneration == 2) tracers(:)%type = 'tag' !--- Set %type: 'tracer' or 'tag' 257 DO it=1,ntrac 258 CALL addKey_1('type', tracers(it)%type, tracers(it)%keys) !--- Set the type of tracer 267 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' 270 DO it = 1, ntrac 271 CALL addKey('type', tracers(it)%type, tracers(it)%keys) !--- Set the type of tracer 259 272 END DO 260 IF(test(checkTracers(tracers, fname, fname), lerr)) RETURN!--- Detect orphans and check phases261 IF(test(checkUnique (tracers, fname, fname), lerr)) RETURN!--- Detect repeated tracers262 CALL sortTracers (tracers)!--- Sort the tracers273 lerr = checkTracers(tracers, fname, fname); IF(lerr) RETURN !--- Detect orphans and check phases 274 lerr = checkUnique (tracers, fname, fname); IF(lerr) RETURN !--- Detect repeated tracers 275 CALL sortTracers (tracers) !--- Sort the tracers 263 276 !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 264 CASE(2); IF(test(feedDBase(["tracer.def"], [type_trac], modname), lerr)) RETURN!=== SINGLE FILE, MULTIPLE SECTIONS277 CASE(2); lerr=feedDBase(["tracer.def"], [type_trac], modname); IF(lerr) RETURN !=== SINGLE FILE, MULTIPLE SECTIONS 265 278 !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 266 CASE(3); IF(test(feedDBase( trac_files , sections, modname), lerr)) RETURN!=== MULTIPLE FILES, SINGLE SECTION279 CASE(3); lerr=feedDBase( trac_files , sections, modname); IF(lerr) RETURN !=== MULTIPLE FILES, SINGLE SECTION 267 280 !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 268 281 END SELECT 269 282 !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 270 283 IF(ALL([2,3] /= fType)) RETURN 271 272 IF(nsec == 1) THEN; 273 tracers = dBase(1)%trac 274 ELSE IF(tracs_merge) THEN 275 CALL msg('The multiple required sections will be MERGED.', modname) 276 IF(test(mergeTracers(dBase, tracers), lerr)) RETURN 277 ELSE 278 CALL msg('The multiple required sections will be CUMULATED.', modname) 279 IF(test(cumulTracers(dBase, tracers), lerr)) RETURN 284 IF(nsec == 1) tracers = dBase(1)%trac 285 IF(nsec /= 1) THEN 286 CALL msg('Multiple sections are MERGED', modname, lTracsMerge) 287 CALL msg('Multiple sections are CUMULATED', modname, .NOT.lTracsMerge) 288 IF( lTracsMerge) lerr = cumulTracers(dBase, tracers) 289 IF(.NOT.lTracsMerge) lerr = cumulTracers(dBase, tracers) 290 IF(lerr) RETURN 280 291 END IF 281 CALL setDirectKeys(tracers) !--- Set %iqParent, %iqDescen, %nqDescen, %nqChildren 292 lerr = indexUpdate(tracers); IF(lerr) RETURN !--- Set iqParent, iqDescen, nqDescen, nqChildren 293 IF(PRESENT(tracs)) CALL MOVE_ALLOC(FROM=tracers, TO=tracs) 282 294 END FUNCTION readTracersFiles 283 295 !============================================================================================================================== … … 299 311 !--- PARSE "type_trac" LIST AND DETERMINE THE TRACERS FILES NAMES (FOR CASE 3: MULTIPLE FILES, SINGLE SECTION PER FILE) 300 312 !--- If type_trac is a scalar (case 1), "sections" and "trac_files" are not usable, but are meaningless for case 1 anyway. 301 IF(test(strParse(type_trac, '|', sections, n=nsec), lerr)) RETURN !--- Parse "type_trac" list313 lerr = strParse(type_trac, '|', sections, n=nsec); IF(lerr) RETURN !--- Parse "type_trac" list 302 314 IF(PRESENT(sects)) sects = sections 303 315 ALLOCATE(trac_files(nsec), ll(nsec)) … … 313 325 IF(.NOT.lD) RETURN !--- NO CHECKING/DISPLAY NEEDED: JUST GET type_trac,fType 314 326 IF(ANY(ll) .AND. fType/=3) THEN !--- MISSING FILES 315 IF(test(checkList(trac_files, .NOT.ll, 'Failed reading tracers description', 'files', 'missing'), lerr)) RETURN327 lerr = checkList(trac_files, .NOT.ll, 'Failed reading tracers description', 'files', 'missing'); IF(lerr) RETURN 316 328 END IF 317 329 … … 344 356 ll = strCount(snames, '|', ndb) !--- Number of sections for each file 345 357 ALLOCATE(ixf(SUM(ndb))) 346 DO i=1, SIZE(fnames) !--- Set %name, %keys347 IF(test(readSections(fnames(i), snames(i), 'default'), lerr)) RETURN358 DO i=1, SIZE(fnames) !--- Set name, keys 359 lerr = readSections(fnames(i), snames(i), 'default'); IF(lerr) RETURN 348 360 ixf(1+SUM(ndb(1:i-1)):SUM(ndb(1:i))) = i !--- File index for each section of the expanded list 349 361 END DO … … 353 365 fnm = fnames(ixf(idb)); snm = dBase(idb)%name !--- FILE AND SECTION NAMES 354 366 lerr = ANY([(dispTraSection('RAW CONTENT OF SECTION "'//TRIM(snm)//'"', snm, modname), idb=1, SIZE(dBase))]) 355 IF(test(expandSection(dBase(idb)%trac, snm, fnm), lerr)) RETURN !--- EXPAND NAMES ; set %parent, %type, %component356 IF(test(setGeneration(dBase(idb)%trac), lerr)) RETURN !--- set %iGeneration, %genOName357 IF(test(checkTracers (dBase(idb)%trac, snm, fnm), lerr)) RETURN!--- CHECK ORPHANS AND PHASES358 IF(test(checkUnique (dBase(idb)%trac, snm, fnm), lerr)) RETURN!--- CHECK TRACERS UNIQUENESS359 CALL expandPhases (dBase(idb)%trac) !--- EXPAND PHASES ; set %phase360 CALL sortTracers (dBase(idb)%trac)!--- SORT TRACERS367 lerr = expandSection(dBase(idb)%trac, snm, fnm); IF(lerr) RETURN !--- EXPAND NAMES ; SET parent, type, component 368 lerr = setGeneration(dBase(idb)%trac); IF(lerr) RETURN !--- SET iGeneration, genOName 369 lerr = checkTracers (dBase(idb)%trac, snm, fnm); IF(lerr) RETURN !--- CHECK ORPHANS AND PHASES 370 lerr = checkUnique (dBase(idb)%trac, snm, fnm); IF(lerr) RETURN !--- CHECK TRACERS UNIQUENESS 371 lerr = expandPhases (dBase(idb)%trac); IF(lerr) RETURN !--- EXPAND PHASES ; set phase 372 CALL sortTracers (dBase(idb)%trac) !--- SORT TRACERS 361 373 lerr = ANY([(dispTraSection('EXPANDED CONTENT OF SECTION "'//TRIM(snm)//'"', snm, modname), idb=1, SIZE(dBase))]) 362 374 !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ … … 387 399 ll = strParse(snam, '|', keys = sec) !--- Requested sections names 388 400 ix = strIdx(dBase(:)%name, sec(:)) !--- Indexes of requested sections in database 389 IF(test(checkList(sec, ix == 0, 'In file "'//TRIM(fnam)//'"','section(s)', 'missing'), lerr)) RETURN401 lerr = checkList(sec, ix == 0, 'In file "'//TRIM(fnam)//'"','section(s)', 'missing'); IF(lerr) RETURN 390 402 tdb = dBase(:); dBase = [tdb(1:n0-1),tdb(PACK(ix, MASK=ix/=0))] !--- Keep requested sections only 391 403 … … 403 415 !------------------------------------------------------------------------------------------------------------------------------ 404 416 IF(.NOT.ALLOCATED(dBase)) ALLOCATE(dBase(0)) 405 OPEN(90, FILE=fnam, FORM='formatted', STATUS='old')417 OPEN(90, FILE=fnam, FORM='formatted', POSITION='REWIND', STATUS='old') 406 418 DO; str='' 407 419 DO … … 416 428 IF(str(1:1)=='#') CYCLE !--- Skip comments lines 417 429 CALL removeComment(str) !--- Skip comments at the end of a line 430 IF(LEN_TRIM(str) == 0) CYCLE !--- Empty line (probably end of file) 418 431 IF(str == '') CYCLE !--- Skip empty line (probably at the end of the file) 419 432 IF(str(1:1)=='&') THEN !=== SECTION HEADER LINE … … 431 444 ll = strParse(str,' ', s, n, v) !--- Parse <key>=<val> pairs 432 445 tt = dBase(ndb)%trac(:) 433 tmp%name = s(1); tmp%keys = keys_type(s(1), s(2:n), v(2:n)) !--- Set %name and %keys 446 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 434 448 dBase(ndb)%trac = [tt(:), tmp] 435 DEALLOCATE(tt) 436 ! dBase(ndb)%trac = [dBase(ndb)%trac(:), tra(name=s(1), keys=keys_type(s(1), s(2:n), v(2:n)))] 449 DEALLOCATE(tt, tmp%keys%key, tmp%keys%val) 437 450 END IF 438 451 END DO … … 460 473 ky => t(jd)%keys 461 474 DO k = 1, SIZE(ky%key) !--- Loop on the keys of the tracer named "defName" 462 ! CALL addKey _m(ky%key(k), ky%val(k), t(:)%keys, .FALSE.)!--- Add key to all the tracers (no overwriting)463 DO it = 1, SIZE(t); CALL addKey _1(ky%key(k), ky%val(k), t(it)%keys, .FALSE.); END DO475 ! 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 464 477 END DO 465 478 tt = [t(1:jd-1),t(jd+1:SIZE(t))]; CALL MOVE_ALLOC(FROM=tt, TO=t) !--- Remove the virtual tracer named "defName" … … 506 519 !------------------------------------------------------------------------------------------------------------------------------ 507 520 TYPE(trac_type), ALLOCATABLE, INTENT(INOUT) :: tr(:) !--- Tracer derived type vector 508 CHARACTER(LEN=*), INTENT(IN) :: sname 509 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: fname 521 CHARACTER(LEN=*), INTENT(IN) :: sname !--- Current section name 522 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: fname !--- Tracers description file name 510 523 TYPE(trac_type), ALLOCATABLE :: ttr(:) 511 CHARACTER(LEN=maxlen), ALLOCATABLE :: ta(:), pa(:) 524 CHARACTER(LEN=maxlen), ALLOCATABLE :: ta(:), pa(:), tname(:), parent(:), dType(:) 512 525 CHARACTER(LEN=maxlen) :: msg1, modname 513 526 INTEGER :: it, nt, iq, nq, itr, ntr, ipr, npr … … 516 529 lerr = .FALSE. 517 530 nt = SIZE(tr) 531 lerr = getKey('name', tname, tr(:)%keys); IF(lerr) RETURN 532 lerr = getKey('parent', parent, tr(:)%keys, def = tran0); IF(lerr) RETURN 533 lerr = getKey('type', dType, tr(:)%keys, def = 'tracer'); IF(lerr) RETURN 518 534 nq = 0 519 535 !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ … … 521 537 !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 522 538 !--- Extract useful keys: parent name, type, component name 523 tr(it)%parent = fgetKey(it, 'parent', tr(:)%keys, tran0 )524 tr(it)%type = fgetKey(it, 'type' , tr(:)%keys, 'tracer')525 539 tr(it)%component = sname 526 ! CALL addKey_m('component', sname, tr(:)%keys) 527 DO iq=1,SIZE(tr); CALL addKey_1('component', sname, tr(iq)%keys); END DO 540 CALL addKey('component', sname, tr(it)%keys) 528 541 529 542 !--- Determine the number of tracers and parents ; coherence checking 530 ll = strCount( tr(it)%name,',', ntr)531 ll = strCount( tr(it)%parent, ',', npr)543 ll = strCount( tname(it), ',', ntr) 544 ll = strCount(parent(it), ',', npr) 532 545 533 546 !--- Tagging tracers only can have multiple parents 534 IF(test(npr/=1 .AND. TRIM(tr(it)%type)/='tag', lerr)) THEN 547 lerr = npr /=1 .AND. TRIM(dType(it)) /= 'tag' 548 IF(lerr) THEN 535 549 msg1 = 'Check section "'//TRIM(sname)//'"' 536 IF(PRESENT(fname)) msg1 =TRIM(msg1)//' in file "'//TRIM(fname)//'"'537 CALL msg(TRIM(msg1)//': "'//TRIM(t r(it)%name)//'" has several parents but is not a tag', modname); RETURN550 IF(PRESENT(fname)) msg1 = TRIM(msg1)//' in file "'//TRIM(fname)//'"' 551 CALL msg(TRIM(msg1)//': "'//TRIM(tname(it))//'" has several parents but is not a tag', modname); RETURN 538 552 END IF 539 553 nq = nq + ntr*npr … … 547 561 DO it = 1, nt !=== EXPAND TRACERS AND PARENTS NAMES LISTS 548 562 !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 549 ll = strParse(tr(it)%name, ',', ta, ntr) !--- Number of tracers 550 ll = strParse(tr(it)%parent, ',', pa, npr) !--- Number of parents 551 DO ipr=1,npr !--- Loop on parents list elts 552 DO itr=1,ntr !--- Loop on tracers list elts 563 ll = strParse( tname(it), ',', ta, ntr) !--- Number of tracers 564 ll = strParse(parent(it), ',', pa, npr) !--- Number of parents 565 DO ipr = 1, npr !--- Loop on parents list elts 566 DO itr = 1, ntr !--- Loop on tracers list elts 567 ttr(iq)%keys%name = TRIM(ta(itr)) 553 568 ttr(iq)%keys%key = tr(it)%keys%key 554 569 ttr(iq)%keys%val = tr(it)%keys%val 555 ttr(iq)%keys%name = ta(itr) 556 ttr(iq)%name = TRIM(ta(itr)); CALL addKey_1('name', ta(itr), ttr(iq)%keys) 557 ttr(iq)%parent = TRIM(pa(ipr)); CALL addKey_1('parent', pa(ipr), ttr(iq)%keys) 558 ttr(iq)%type = tr(it)%type; CALL addKey_1('type', tr(it)%type, ttr(iq)%keys) 559 ttr(iq)%component = tr(it)%component; CALL addKey_1('component', tr(it)%component, ttr(iq)%keys) 560 iq = iq+1 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) 578 iq = iq + 1 561 579 END DO 562 580 END DO … … 575 593 !------------------------------------------------------------------------------------------------------------------------------ 576 594 ! Purpose: Determine, for each tracer of "tr(:)": 577 ! * %iGeneration: the generation number578 ! * %gen0Name: the generation 0 ancestor name579 ! Check also for orphan tracers (tracers not descending on "tran0").595 ! * iGeneration: the generation number 596 ! * gen0Name: the generation 0 ancestor name 597 ! Check also for orphan tracers (tracers without parent). 580 598 !------------------------------------------------------------------------------------------------------------------------------ 581 599 TYPE(trac_type), INTENT(INOUT) :: tr(:) !--- Tracer derived type vector 582 600 INTEGER :: iq, jq, ig 583 CHARACTER(LEN=maxlen), ALLOCATABLE :: parent(:) 601 CHARACTER(LEN=maxlen), ALLOCATABLE :: parent(:), tname(:) 584 602 !------------------------------------------------------------------------------------------------------------------------------ 585 603 CHARACTER(LEN=maxlen) :: modname 586 604 modname = 'setGeneration' 587 IF(test(fmsg('missing "parent" attribute', modname, getKey('parent', parent, ky=tr(:)%keys)), lerr)) RETURN 605 lerr = getKey('name', tname, ky=tr(:)%keys); IF(lerr) RETURN 606 lerr = getKey('parent', parent, ky=tr(:)%keys); IF(lerr) RETURN 588 607 DO iq = 1, SIZE(tr) 589 608 jq = iq; ig = 0 590 609 DO WHILE(parent(jq) /= tran0) 591 jq = strIdx(tr(:)%name, parent(jq)) 592 IF(test(fmsg('Orphan tracer "'//TRIM(tr(iq)%name)//'"', modname, jq == 0), lerr)) RETURN 610 jq = strIdx(tname(:), parent(jq)) 611 lerr = jq == 0 612 IF(fmsg('Orphan tracer "'//TRIM(tname(iq))//'"', modname, lerr)) RETURN 593 613 ig = ig + 1 594 614 END DO 595 tr(iq)%gen0Name = tr(jq)%name; CALL addKey_1('gen0Name', tr(iq)%gen0Name, tr(iq)%keys) 596 tr(iq)%iGeneration = ig; CALL addKey_1('iGeneration', TRIM(int2str(ig)), tr(iq)%keys) 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) 597 619 END DO 598 620 END FUNCTION setGeneration … … 604 626 !------------------------------------------------------------------------------------------------------------------------------ 605 627 ! Purpose: 606 ! * check for orphan tracers (without knownparent)607 ! * check wether the phases are known or not ( "g"aseous, "l"iquid or "s"olid so far)628 ! * check for orphan tracers (without parent) 629 ! * check wether the phases are known or not (elements of "known_phases") 608 630 !------------------------------------------------------------------------------------------------------------------------------ 609 631 TYPE(trac_type), INTENT(IN) :: tr(:) !--- Tracer derived type vector 610 632 CHARACTER(LEN=*), INTENT(IN) :: sname !--- Section name 611 633 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: fname !--- File name 634 CHARACTER(LEN=1) :: p 612 635 CHARACTER(LEN=maxlen) :: mesg 613 636 CHARACTER(LEN=maxlen) :: bp(SIZE(tr, DIM=1)), pha !--- Bad phases list, phases of current tracer 614 CHARACTER(LEN=1) :: p 637 CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:) 638 INTEGER, ALLOCATABLE :: iGen(:) 615 639 INTEGER :: ip, np, iq, nq 616 640 !------------------------------------------------------------------------------------------------------------------------------ 641 CHARACTER(LEN=maxlen) :: modname 642 modname = 'checkTracers' 617 643 nq = SIZE(tr,DIM=1) !--- Number of tracers lines 618 644 mesg = 'Check section "'//TRIM(sname)//'"' 619 645 IF(PRESENT(fname)) mesg=TRIM(mesg)//' in file "'//TRIM(fname)//'"' 646 lerr = getKey('iGeneration', iGen, tr(:)%keys); IF(lerr) RETURN 647 lerr = getKey('name', tname, tr(:)%keys); IF(lerr) RETURN 620 648 621 649 !=== CHECK FOR ORPHAN TRACERS 622 IF(test(checkList(tr%name, tr%iGeneration==-1, mesg, 'tracers', 'orphan'), lerr)) RETURN650 lerr = checkList(tname, iGen==-1, mesg, 'tracers', 'orphan'); IF(lerr) RETURN 623 651 624 652 !=== CHECK PHASES 625 DO iq =1,nq; IF(tr(iq)%iGeneration/=0) CYCLE!--- Generation O only is checked626 pha = fgetKey(iq, 'phases', tr(:)%keys, 'g') !--- Phases653 DO iq = 1, nq; IF(iGen(iq) /= 0) CYCLE !--- Generation O only is checked 654 IF(getKey(['phases','phase '], pha, iq, tr(:)%keys, lDisp=.FALSE.)) pha = 'g' !--- Phase 627 655 np = LEN_TRIM(pha); bp(iq)=' ' 628 DO ip =1,np; p = pha(ip:ip); IF(INDEX(known_phases,p)==0) bp(iq) = TRIM(bp(iq))//p; END DO629 IF(TRIM(bp(iq)) /= '') bp(iq) = TRIM(t r(iq)%name)//': '//TRIM(bp(iq))656 DO ip = 1, np; p = pha(ip:ip); IF(INDEX(known_phases, p) == 0) bp(iq) = TRIM(bp(iq))//p; END DO 657 IF(TRIM(bp(iq)) /= '') bp(iq) = TRIM(tname(iq))//': '//TRIM(bp(iq)) 630 658 END DO 631 lerr = checkList(bp, tr%iGeneration==0 .AND. bp/='', mesg, 'tracers phases', 'unknown')659 lerr = checkList(bp, iGen == 0 .AND. bp /= '', mesg, 'tracers phases', 'unknown') 632 660 END FUNCTION checkTracers 633 661 !============================================================================================================================== … … 645 673 INTEGER :: ip, np, iq, nq, k 646 674 LOGICAL, ALLOCATABLE :: ll(:) 647 CHARACTER(LEN=maxlen) :: mesg, tnam, tdup(SIZE(tr,DIM=1)) 648 CHARACTER(LEN=1) :: p 649 !------------------------------------------------------------------------------------------------------------------------------ 675 CHARACTER(LEN=maxlen) :: mesg, phase, tdup(SIZE(tr,DIM=1)) 676 CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:), dType(:) 677 INTEGER, ALLOCATABLE :: iGen(:) 678 CHARACTER(LEN=1) :: p 679 !------------------------------------------------------------------------------------------------------------------------------ 680 CHARACTER(LEN=maxlen) :: modname 681 modname = 'checkUnique' 650 682 mesg = 'Check section "'//TRIM(sname)//'"' 651 683 IF(PRESENT(fname)) mesg=TRIM(mesg)//' in file "'//TRIM(fname)//'"' 652 684 nq=SIZE(tr,DIM=1); lerr=.FALSE. !--- Number of lines ; error flag 653 685 tdup(:) = '' 654 DO iq=1,nq; IF(tr(iq)%type == 'tag') CYCLE !--- Tags can be repeated 655 tnam = TRIM(tr(iq)%name) 656 ll = tr(:)%name==TRIM(tnam) !--- Mask for current tracer name 657 IF(COUNT(ll)==1 ) CYCLE !--- Tracer is not repeated 658 IF(tr(iq)%iGeneration>0) THEN 659 tdup(iq) = tnam !--- gen>0: MUST be unique 686 lerr = getKey('name', tname, tr%keys); IF(lerr) RETURN 687 lerr = getKey('type', dType, tr%keys); IF(lerr) RETURN 688 lerr = getKey('iGeneration', iGen, tr%keys); IF(lerr) RETURN 689 DO iq = 1, nq 690 IF(dType(iq) == 'tag') CYCLE !--- Tags can be repeated 691 ll = tname==TRIM(tname(iq)) !--- Mask for current tracer name 692 IF(COUNT(ll) == 1) CYCLE !--- Tracer is not repeated 693 IF(iGen(iq) > 0) THEN 694 tdup(iq) = tname(iq) !--- gen>0: MUST be unique 660 695 ELSE 661 DO ip=1,nphases; p=known_phases(ip:ip) !--- Loop on known phases 662 !--- Number of appearances of the current tracer with known phase "p" 663 np = COUNT( PACK( [(INDEX(fgetKey(k, 'phases', tr(:)%keys, 'g'),p), k=1, nq)] /=0 , MASK=ll ) ) 664 IF(np <=1) CYCLE 665 tdup(iq) = TRIM(tdup(iq))//TRIM(phases_names(ip)) 696 DO ip = 1, nphases; p = known_phases(ip:ip) !--- Loop on known phases 697 np = 0 698 DO k = 1, nq 699 IF(.NOT.ll(k)) CYCLE !--- Skip tracers different from current one 700 IF(getKey(['phases','phase '], phase, k, tr%keys, lDisp=.FALSE.)) phase='g'!--- Get current phases 701 IF(INDEX(phase, p) /= 0) np = np + 1 !--- One more appearance of current tracer with phase "p" 702 END DO 703 IF(np <= 1) CYCLE !--- Regular case: no or a single appearance 704 tdup(iq) = TRIM(tdup(iq))//TRIM(phases_names(ip)) !--- Repeated phase 666 705 IF(ANY(tdup(1:iq-1) == tdup(iq))) tdup(iq)='' !--- Avoid repeating same messages 667 706 END DO 668 707 END IF 669 IF(tdup(iq) /= '') tdup(iq)=TRIM(tnam )//' in '//TRIM(tdup(iq))//' phase(s)'708 IF(tdup(iq) /= '') tdup(iq)=TRIM(tname(iq))//' in '//TRIM(tdup(iq))//' phase(s)' 670 709 END DO 671 710 lerr = checkList(tdup, tdup/='', mesg, 'tracers', 'duplicated') … … 675 714 676 715 !============================================================================================================================== 677 SUBROUTINE expandPhases(tr)716 LOGICAL FUNCTION expandPhases(tr) RESULT(lerr) 678 717 !------------------------------------------------------------------------------------------------------------------------------ 679 718 ! Purpose: Expand the phases in the tracers descriptor "tr". Phases are not repeated for a tracer, thanks to "checkUnique". … … 681 720 TYPE(trac_type), ALLOCATABLE, INTENT(INOUT) :: tr(:) !--- Tracer derived type vector 682 721 !------------------------------------------------------------------------------------------------------------------------------ 683 TYPE(trac_type), ALLOCATABLE :: ttr(:) 684 INTEGER, ALLOCATABLE :: i0(:) 685 CHARACTER(LEN=maxlen) :: nam, pha, tname 722 TYPE(trac_type), ALLOCATABLE :: ttr(:) 723 INTEGER, ALLOCATABLE :: i0(:), iGen(:) 724 CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:), gen0N(:), phase(:), parents(:), dType(:) 725 CHARACTER(LEN=maxlen) :: nam, gen0Nm, pha, parent 686 726 CHARACTER(LEN=1) :: p 687 727 INTEGER :: ip, np, iq, jq, nq, it, nt, nc, i, n 688 728 LOGICAL :: lTag, lExt 689 729 !------------------------------------------------------------------------------------------------------------------------------ 730 CHARACTER(LEN=maxlen) :: modname 731 modname = 'expandPhases' 690 732 nq = SIZE(tr, DIM=1) 691 733 nt = 0 734 lerr = getKey('name', tname, tr%keys); IF(lerr) RETURN !--- Names of the tracers 735 lerr = getKey('gen0Name', gen0N, tr%keys); IF(lerr) RETURN !--- Names of the tracers of first generation 736 lerr = getKey('iGeneration', iGen, tr%keys); IF(lerr) RETURN !--- Generation number 737 lerr = getKey('phases', phase, tr%keys); IF(lerr) RETURN !--- Phases names 738 lerr = getKey('parent', parents, tr%keys); IF(lerr) RETURN !--- Parents names 739 lerr = getKey('type', dType, tr%keys); IF(lerr) RETURN !--- Tracers types ('tracer' or 'tag') 692 740 DO iq = 1, nq !--- GET THE NUMBER OF TRACERS 693 IF(tr(iq)%iGeneration /= 0) CYCLE !--- Only deal with generation 0 tracers 694 nc = COUNT(tr(:)%gen0Name==tr(iq)%name .AND. tr%iGeneration/=0) !--- Number of children of tr(iq) 695 tr(iq)%phase = fgetKey(iq, 'phases', tr(:)%keys) !--- Phases list of tr(iq) 696 np = LEN_TRIM(tr(iq)%phase) !--- Number of phases of tr(iq) 741 IF(iGen(iq) /= 0) CYCLE !--- Only deal with generation 0 tracers 742 nc = COUNT(gen0N == tname(iq) .AND. iGen /= 0) !--- Number of children of tr(iq) 743 np = LEN_TRIM(phase(iq)) !--- Number of phases of tr(iq) 697 744 nt = nt + (1+nc) * np !--- Number of tracers after expansion 698 745 END DO … … 700 747 it = 1 !--- Current "ttr(:)" index 701 748 DO iq = 1, nq !--- Loop on "tr(:)" indexes 702 lTag = tr(iq)%type=='tag'!--- Current tracer is a tag703 i0 = strFind(t r(:)%name, TRIM(tr(iq)%gen0Name), n)!--- Indexes of first generation ancestor copies704 np = SUM([( LEN_TRIM( tr(i0(i))%phase),i=1,n )], 1)!--- Number of phases for current tracer tr(iq)705 lExt = np >1!--- Phase suffix only required if phases number is > 1706 IF(lTag) lExt = lExt .AND. tr(iq)%iGeneration>0!--- No phase suffix for generation 0 tags707 DO i =1,n!=== LOOP ON GENERATION 0 ANCESTORS749 lTag = dType(iq)=='tag' !--- Current tracer is a tag 750 i0 = strFind(tname, TRIM(gen0N(iq)), n) !--- Indexes of first generation ancestor copies 751 np = SUM([( LEN_TRIM(phase(i0(i))), i = 1, n )], 1) !--- Number of phases for current tracer tr(iq) 752 lExt = np > 1 !--- Phase suffix only required if phases number is > 1 753 IF(lTag) lExt = lExt .AND. iGen(iq) > 0 !--- No phase suffix for generation 0 tags 754 DO i = 1, n !=== LOOP ON GENERATION 0 ANCESTORS 708 755 jq = i0(i) !--- tr(jq): ith tracer with same gen 0 ancestor as tr(iq) 709 IF( tr(iq)%iGeneration==0) jq=iq!--- Generation 0: count the current tracer phases only710 pha = tr(jq)%phase!--- Phases list for tr(jq)756 IF(iGen(iq) == 0) jq = iq !--- Generation 0: count the current tracer phases only 757 pha = phase(jq) !--- Phases list for tr(jq) 711 758 DO ip = 1, LEN_TRIM(pha) !=== LOOP ON PHASES LISTS 712 759 p = pha(ip:ip) 713 tname = TRIM(tr(iq)%name); nam = tname!--- Tracer name (regular case)714 IF(lTag) nam = TRIM( tr(iq)%parent)!--- Parent name (tagging case)760 nam = tname(iq) !--- Tracer name (regular case) 761 IF(lTag) nam = TRIM(parents(iq)) !--- Parent name (tagging case) 715 762 IF(lExt) nam = addPhase(nam, p ) !--- Phase extension needed 716 IF(lTag) nam = TRIM(nam)//'_'//TRIM(tname )!--- <parent>_<name> for tags763 IF(lTag) nam = TRIM(nam)//'_'//TRIM(tname(iq)) !--- <parent>_<name> for tags 717 764 ttr(it) = tr(iq) !--- Same <key>=<val> pairs 718 765 ttr(it)%name = TRIM(nam) !--- Name with possibly phase suffix 719 766 ttr(it)%keys%name = TRIM(nam) !--- Name inside the keys decriptor 720 767 ttr(it)%phase = p !--- Single phase entry 721 CALL addKey_1('name', nam, ttr(it)%keys) 722 CALL addKey_1('phase', p, ttr(it)%keys) 723 IF(lExt .AND. tr(iq)%iGeneration>0) THEN 724 ttr(it)%parent = addPhase(tr(iq)%parent, p) 725 ttr(it)%gen0Name = addPhase(tr(iq)%gen0Name, p) 726 CALL addKey_1('parent', ttr(it)%parent, ttr(it)%keys) 727 CALL addKey_1('gen0Name', ttr(it)%gen0Name, ttr(it)%keys) 768 CALL addKey('name', nam, ttr(it)%keys) 769 CALL addKey('phase', p, ttr(it)%keys) 770 IF(lExt) THEN 771 parent = parents(iq); IF(iGen(iq) > 0) parent = addPhase(parent, p) 772 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) 728 777 END IF 729 778 it = it+1 730 779 END DO 731 IF( tr(iq)%iGeneration==0) EXIT!--- Break phase loop for gen 0780 IF(iGen(iq) == 0) EXIT !--- Break phase loop for gen 0 732 781 END DO 733 782 END DO … … 735 784 CALL delKey(['phases'],tr) !--- Remove few keys entries 736 785 737 END SUBROUTINEexpandPhases786 END FUNCTION expandPhases 738 787 !============================================================================================================================== 739 788 … … 748 797 ! TO BE ADDED IF NECESSARY: HIGHER MOMENTS AT THE END 749 798 !------------------------------------------------------------------------------------------------------------------------------ 750 TYPE(trac_type), ALLOCATABLE, INTENT(INOUT) :: tr(:) !--- Tracer derived type vector 751 !------------------------------------------------------------------------------------------------------------------------------ 752 TYPE(trac_type), ALLOCATABLE :: tr2(:) 753 INTEGER, ALLOCATABLE :: iy(:), iz(:) 754 INTEGER :: ig, ng, iq, jq, ip, nq, n, ix(SIZE(tr)), k 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(:) 804 CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:), gen0N(:) 805 INTEGER :: ig, ng, iq, jq, ip, nq, n, ix(SIZE(tr)), k 806 LOGICAL :: lerr 755 807 ! tr2 is introduced in order to cope with a bug in gfortran 4.8.5 compiler 756 808 !------------------------------------------------------------------------------------------------------------------------------ 809 lerr = getKey('iGeneration', iGen, tr%keys); IF(lerr) RETURN !--- Generation number 757 810 nq = SIZE(tr) 758 811 DO ip = nphases, 1, -1 759 iq = strIdx(tr(:)%name, addPhase('H2O', ip)) 812 lerr = getKey('name', tname, tr%keys); IF(lerr) RETURN !--- Names of the tracers of first generation 813 iq = strIdx(tname, addPhase('H2O', ip)) 760 814 IF(iq == 0) CYCLE 761 815 tr2 = tr(:) … … 764 818 IF(lSortByGen) THEN 765 819 iq = 1 766 ng = MAXVAL( tr(:)%iGeneration, MASK=.TRUE., DIM=1)!--- Number of generations820 ng = MAXVAL(iGen, MASK=.TRUE., DIM=1) !--- Number of generations 767 821 DO ig = 0, ng !--- Loop on generations 768 iy = PACK([(k, k=1, nq)], MASK= tr(:)%iGeneration==ig)!--- Generation ig tracers indexes822 iy = PACK([(k, k=1, nq)], MASK=iGen(:) == ig) !--- Generation ig tracers indexes 769 823 n = SIZE(iy) 770 824 ix(iq:iq+n-1) = iy !--- Stack growing generations idxs … … 772 826 END DO 773 827 ELSE 774 iq = 1828 lerr = getKey('gen0Name', gen0N, tr%keys); IF(lerr) RETURN !--- Names of the tracers iq = 1 775 829 DO jq = 1, nq !--- Loop on generation 0 tracers 776 IF( tr(jq)%iGeneration /= 0) CYCLE!--- Skip generations /= 0830 IF(iGen(jq) /= 0) CYCLE !--- Skip generations /= 0 777 831 ix(iq) = jq !--- Generation 0 ancestor index first 778 832 iq = iq + 1 !--- Next "iq" for next generations tracers 779 iy = strFind( tr(:)%gen0Name, TRIM(tr(jq)%name)) !--- Indexes of "tr(jq)" children in "tr(:)"780 ng = MAXVAL( tr(iy)%iGeneration, MASK=.TRUE., DIM=1)!--- Number of generations of the "tr(jq)" family833 iy = strFind(gen0N(:), TRIM(tname(jq))) !--- Indices of "tr(jq)" children in "tr(:)" 834 ng = MAXVAL(iGen(iy), MASK=.TRUE., DIM=1) !--- Number of generations of the "tr(jq)" family 781 835 DO ig = 1, ng !--- Loop on generations of the "tr(jq)" family 782 iz = find( tr(iy)%iGeneration, ig, n) !--- Indexes of the tracers "tr(iy(:))" of generation "ig"836 iz = find(iGen(iy), ig, n) !--- Indices of the tracers "tr(iy(:))" of generation "ig" 783 837 ix(iq:iq+n-1) = iy(iz) !--- Same indexes in "tr(:)" 784 838 iq = iq + n … … 796 850 TYPE(trac_type), ALLOCATABLE, INTENT(OUT) :: tr(:) 797 851 TYPE(trac_type), POINTER :: t1(:), t2(:) 852 TYPE(keys_type), POINTER :: k1(:), k2(:) 798 853 INTEGER, ALLOCATABLE :: ixct(:), ixck(:) 799 INTEGER :: is, k1,k2, nk2, i1, i2, nt2854 INTEGER :: is, ik, ik1, ik2, nk2, i1, i2, nt2 800 855 CHARACTER(LEN=maxlen) :: s1, v1, v2, tnam, knam, modname 856 CHARACTER(LEN=maxlen), ALLOCATABLE :: keys(:), n1(:), n2(:) 801 857 modname = 'mergeTracers' 802 858 lerr = .FALSE. 803 t1 => sections(1)%trac(:) !--- Alias: first tracers section 859 keys = ['parent ', 'type ', 'iGeneration'] !--- Mandatory keys 860 t1 => sections(1)%trac(:); k1 => t1(:)%keys !--- Alias: first tracers section, corresponding keys 861 lerr = getKey('name', n1, k1); IF(lerr) RETURN !--- Names of the tracers 804 862 tr = t1 805 863 !---------------------------------------------------------------------------------------------------------------------------- … … 807 865 !---------------------------------------------------------------------------------------------------------------------------- 808 866 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 809 869 nt2 = SIZE(t2(:), DIM=1) !--- Number of tracers in section 810 ixct = strIdx( t1(:)%name, t2(:)%name)!--- Indexes of common tracers870 ixct = strIdx(n1(:), n2(:)) !--- Indexes of common tracers 811 871 tr = [tr, PACK(t2, MASK= ixct==0)] !--- Append with new tracers 812 872 IF( ALL(ixct == 0) ) CYCLE !--- No common tracers => done 813 873 CALL msg('Tracers defined in previous sections and duplicated in "'//TRIM(sections(is)%name)//'":', modname) 814 CALL msg( t1(PACK(ixct, MASK = ixct/=0))%name, modname, nmax=128)!--- Display duplicates (the 128 first at most)874 CALL msg(n1(PACK(ixct, MASK = ixct/=0)), modname, nmax=128) !--- Display duplicates (the 128 first at most) 815 875 !-------------------------------------------------------------------------------------------------------------------------- 816 876 DO i2=1,nt2; tnam = TRIM(t2(i2)%name) !=== LOOP ON COMMON TRACERS … … 820 880 !=== CHECK WETHER ESSENTIAL KEYS ARE IDENTICAL OR NOT 821 881 s1=' of "'//TRIM(tnam)//'" in "'//TRIM(sections(is)%name)//'" not matching previous value' 822 823 IF(test(fmsg('Parent name'//TRIM(s1), modname, t1(i1)%parent /= t2(i2)%parent), lerr)) RETURN824 IF(test(fmsg('Type' //TRIM(s1), modname, t1(i1)%type /= t2(i2)%type), lerr)) RETURN825 IF(test(fmsg('Generation' //TRIM(s1), modname, t1(i1)%iGeneration /= t2(i2)%iGeneration), lerr)) RETURN826 827 !=== APPEND <key>=<val> PAIRS NOT PREVIOULSLY DEFINED 828 nk2 = SIZE(t2(i2)%keys%key(:)) !--- Keys number in current section829 ixck = strIdx(t1(i1)%keys%key(:), t2(i2)%keys%key(:)) !--- Common keys indexes830 831 ! === APPEND NEW KEYS882 DO ik = 1, SIZE(keys) 883 lerr = getKey(keys(ik), v1, i1, k1) 884 lerr = getKey(keys(ik), v2, i2, k2) 885 lerr = v1 /= v2; IF(fmsg(TRIM(keys(ik))//TRIM(s1), modname, lerr)) RETURN 886 END DO 887 888 !=== GET THE INDICES IN tr(i2)%keys%key(:) OF THE KEYS ALSO PRESENT IN tr(i1)%keys%key(:) 889 nk2 = SIZE(k2(i2)%key(:)) !--- Keys number in current section 890 ixck = strIdx(k1(i1)%key(:), k2(i2)%key(:)) !--- Common keys indexes 891 !--- APPEND THE NEW KEYS PAIRS IN tr(i1)%keys%key(:) 832 892 tr(i1)%keys%key = [ tr(i1)%keys%key, PACK(tr(i2)%keys%key, MASK = ixck==0)] 833 893 tr(i1)%keys%val = [ tr(i1)%keys%val, PACK(tr(i2)%keys%val, MASK = ixck==0)] 834 894 835 !--- KEEP TRACK OF THE COMPONENTS NAMES 836 tr(i1)%component = TRIM(tr(i1)%component)//','//TRIM(tr(i2)%component) 837 838 !--- SELECT COMMON TRACERS WITH DIFFERING KEYS VALUES (PREVIOUS VALUE IS KEPT) 839 DO k2=1,nk2 840 k1 = ixck(k2); IF(k1 == 0) CYCLE 841 IF(t1(i1)%keys%val(k1) == t2(i2)%keys%val(k2)) ixck(k2)=0 895 !=== 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) 900 901 !=== FOR TRACERS COMMON TO PREVIOUS AND CURRENT SECTIONS: CHECK WETHER SOME KEYS HAVE DIFFERENT VALUES ; KEEP OLD ONE 902 DO ik2 = 1, nk2 !--- Collect the corresponding indices 903 ik1 = ixck(ik2); IF(ik1 == 0) CYCLE 904 IF(k1(i1)%val(ik1) == k2(i2)%val(ik2)) ixck(ik2)=0 842 905 END DO 843 IF(ALL(ixck==0)) CYCLE !--- No identical keys with /=values 844 845 !--- DISPLAY INFORMATION: OLD VALUES ARE KEPT FOR THE KEYS FOUND IN PREVIOUS AND CURRENT SECTIONS 846 CALL msg('Key(s)'//TRIM(s1), modname) 847 DO k2 = 1, nk2 !--- Loop on keys found in both t1(:) and t2(:) 848 knam = t2(i2)%keys%key(k2) !--- Name of the current key 849 k1 = ixck(k2) !--- Corresponding index in t1(:) 850 IF(k1 == 0) CYCLE !--- New keys are skipped 851 v1 = t1(i1)%keys%val(k1); v2 = t2(i2)%keys%val(k2) !--- Key values in t1(:) and t2(:) 906 IF(ALL(ixck==0)) CYCLE !--- No identical keys with /=values => nothing to display 907 CALL msg('Key(s)'//TRIM(s1), modname) !--- Display the keys with /=values (names list) 908 DO ik2 = 1, nk2 !--- Loop on keys found in both t1(:) and t2(:) 909 knam = k2(i2)%key(ik2) !--- Name of the current key 910 ik1 = ixck(ik2) !--- Corresponding index in t1(:) 911 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(:) 852 913 CALL msg(' * '//TRIM(knam)//'='//TRIM(v2)//' ; previous value kept:'//TRIM(v1), modname) 853 914 END DO … … 862 923 863 924 !============================================================================================================================== 864 LOGICAL FUNCTION cumulTracers(sections, tr ) RESULT(lerr)925 LOGICAL FUNCTION cumulTracers(sections, tr, lRename) RESULT(lerr) 865 926 TYPE(dataBase_type), TARGET, INTENT(IN) :: sections(:) 866 927 TYPE(trac_type), ALLOCATABLE, INTENT(OUT) :: tr(:) 867 TYPE(trac_type), POINTER :: t(:) 868 INTEGER, ALLOCATABLE :: nt(:) 869 CHARACTER(LEN=maxlen) :: tnam, tnam_new 870 INTEGER :: iq, nq, is, ns, nsec 871 lerr = .FALSE. !--- Can't fail ; kept to match "mergeTracer" interface. 872 nsec = SIZE(sections) 873 tr = [( sections(is)%trac(:) , is=1, nsec )] !--- Concatenated tracers vector 874 nt = [( SIZE(sections(is)%trac(:)), is=1, nsec )] !--- Number of tracers in each section 928 LOGICAL, OPTIONAL, INTENT(IN) :: lRename !--- .TRUE.: add a section suffix to identical names 929 CHARACTER(LEN=maxlen) :: tnam_new, modname 930 CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:), parent(:), comp(:) 931 INTEGER :: iq, jq, is 932 modname = 'cumulTracers' 933 lerr = .FALSE. 934 tr = [( sections(is)%trac(:), is = 1, SIZE(sections) )] !--- Concatenated tracers vector 935 IF(PRESENT(lRename)) THEN; IF(lRename) RETURN; END IF !--- No renaming: finished 936 lerr = getKey('name', tname, tr%keys); IF(lerr) RETURN !--- Names 937 lerr = getKey('parent', parent, tr%keys); IF(lerr) RETURN !--- Parents 938 lerr = getKey('component', comp, tr%keys); IF(lerr) RETURN !--- Component name 875 939 !---------------------------------------------------------------------------------------------------------------------------- 876 DO i s=1, nsec !=== LOOP ON SECTIONS940 DO iq = 1, SIZE(tr); IF(COUNT(tname == tname(iq)) == 1) CYCLE !=== LOOP ON TRACERS 877 941 !---------------------------------------------------------------------------------------------------------------------------- 878 t => sections(is)%trac(:) 942 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 879 945 !-------------------------------------------------------------------------------------------------------------------------- 880 DO iq=1, nt(is) !=== LOOP ON TRACERS946 DO jq = 1, SIZE(tr); IF(parent(jq) /= tname(iq)) CYCLE !=== LOOP ON TRACERS PARENTS 881 947 !-------------------------------------------------------------------------------------------------------------------------- 882 tnam = TRIM(t(iq)%name) !--- Original name 883 IF(COUNT(t%name == tnam) == 1) CYCLE !--- Current tracer is not duplicated: finished 884 tnam_new = TRIM(tnam)//'_'//TRIM(sections(is)%name) !--- Same with section extension 885 nq = SUM(nt(1:is-1)) !--- Number of tracers in previous sections 886 ns = nt(is) !--- Number of tracers in the current section 887 tr(iq + nq)%name = TRIM(tnam_new) !--- Modify tracer name 888 WHERE(tr(1+nq:ns+nq)%parent==tnam) tr(1+nq:ns+nq)%parent=tnam_new !--- Modify parent name 948 CALL addKey('parent', tnam_new, tr(jq)%keys) !--- Modify tracer name 949 tr(jq)%parent = TRIM(tnam_new) !--- Modify tracer name 889 950 !-------------------------------------------------------------------------------------------------------------------------- 890 951 END DO … … 896 957 !============================================================================================================================== 897 958 898 !============================================================================================================================== 899 SUBROUTINE setDirectKeys(tr) 959 960 !============================================================================================================================== 961 LOGICAL FUNCTION dispTraSection(message, sname, modname) RESULT(lerr) 962 CHARACTER(LEN=*), INTENT(IN) :: message, sname, modname 963 CHARACTER(LEN=maxlen), ALLOCATABLE :: s(:,:), n(:), tmp(:) 964 CHARACTER(LEN=maxlen) :: p 965 INTEGER :: idb, iq, nq 966 idb = strIdx(dBase(:)%name, sname); IF(idb == 0) RETURN 967 nq = SIZE(dBase(idb)%trac) 968 p = '' 969 CALL append(['iq'], .TRUE. ); IF(lerr) RETURN 970 CALL append(['name'], .TRUE. ); IF(lerr) RETURN 971 CALL append(['phases','phase '], .FALSE., 'pha'); IF(lerr) RETURN 972 CALL append(['hadv'], .TRUE. ); IF(lerr) RETURN 973 CALL append(['vadv'], .TRUE. ); IF(lerr) RETURN 974 CALL append(['parent'], .FALSE.); IF(lerr) RETURN 975 CALL append(['iGen'], .FALSE.); IF(lerr) RETURN 976 CALL msg(TRIM(message)//':', modname) 977 lerr = dispTable(p, n, s, nColMax=maxTableWidth, nHead=2, sub=modname); IF(lerr) RETURN 978 979 CONTAINS 980 981 SUBROUTINE append(nam, lMandatory, snam) 982 ! Test whether key named "nam(:)" is available. 983 ! * yes: - get its value for all species in "tmp(:)" and append table "s(:,:)" with it 984 ! - append titles list with "nam(1)" (or, if specified, "snam", usually a short name). 985 ! * no: return to calling routine with an error flag if the required key is mandatory 986 CHARACTER(LEN=*), INTENT(IN) :: nam(:) 987 LOGICAL, INTENT(IN) :: lMandatory 988 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: snam 989 INTEGER :: m 990 CHARACTER(LEN=maxlen), ALLOCATABLE :: n0(:) 991 CHARACTER(LEN=maxlen) :: nm 992 lerr = .FALSE. 993 IF(nam(1) == 'iq') THEN 994 tmp = int2str([(iq, iq=1, nq)]) 995 ELSE 996 lerr = getKey(nam, tmp, dBase(idb)%trac(:)%keys, lDisp=lMandatory) 997 END IF 998 IF(lerr) THEN; lerr = lMandatory; RETURN; END IF 999 nm = nam(1); IF(PRESENT(snam)) nm = snam 1000 p = TRIM(p)//'s' 1001 IF(ALLOCATED(s)) THEN; s = cat(s, tmp); ELSE; ALLOCATE(s(nq,1)); s(:,1) = tmp; END IF 1002 IF(ALLOCATED(n)) THEN; m = SIZE(n); ALLOCATE(n0(m+1)); n0(1:m)=n; n0(m+1)=nm; CALL MOVE_ALLOC(FROM=n0, TO=n) 1003 ELSE; n=nam(1:1); END IF 1004 END SUBROUTINE append 1005 1006 END FUNCTION dispTraSection 1007 !============================================================================================================================== 1008 1009 1010 !============================================================================================================================== 1011 !=== CREATE TRACER(S) ALIAS: SCALAR/VECTOR FROM NAME(S) OR INDICE(S) ========================================================== 1012 !============================================================================================================================== 1013 LOGICAL FUNCTION aliasTracer(tname, trac, alias) RESULT(lerr) !=== TRACER NAMED "tname" - SCALAR 1014 CHARACTER(LEN=*), INTENT(IN) :: tname 1015 TYPE(trac_type), TARGET, INTENT(IN) :: trac(:) 1016 TYPE(trac_type), POINTER, INTENT(OUT) :: alias 1017 INTEGER :: it 1018 CHARACTER(LEN=maxlen), ALLOCATABLE :: tnames(:) 1019 alias => NULL() 1020 lerr = getKey('name', tnames, trac(:)%keys) 1021 it = strIdx(tnames, tname) 1022 lerr = it /= 0; IF(.NOT.lerr) alias => trac(it) 1023 END FUNCTION aliasTracer 1024 !============================================================================================================================== 1025 LOGICAL FUNCTION trSubset_Indx(trac, idx, alias) RESULT(lerr) !=== TRACERS WITH INDICES "idx(:)" - VECTOR 1026 TYPE(trac_type), ALLOCATABLE, INTENT(IN) :: trac(:) 1027 INTEGER, INTENT(IN) :: idx(:) 1028 TYPE(trac_type), ALLOCATABLE, INTENT(OUT) :: alias(:) 1029 alias = trac(idx) 1030 lerr = indexUpdate(alias) 1031 END FUNCTION trSubset_Indx 1032 !------------------------------------------------------------------------------------------------------------------------------ 1033 LOGICAL FUNCTION trSubset_Name(trac, tname, alias) RESULT(lerr) !=== TRACERS NAMED "tname(:)" - VECTOR 1034 TYPE(trac_type), ALLOCATABLE, INTENT(IN) :: trac(:) 1035 CHARACTER(LEN=*), INTENT(IN) :: tname(:) 1036 TYPE(trac_type), ALLOCATABLE, INTENT(OUT) :: alias(:) 1037 CHARACTER(LEN=maxlen), ALLOCATABLE :: tnames(:) 1038 lerr = getKey('name', tnames, trac(:)%keys) 1039 alias = trac(strIdx(tnames, tname)) 1040 lerr = indexUpdate(alias) 1041 END FUNCTION trSubset_Name 1042 !============================================================================================================================== 1043 LOGICAL FUNCTION trSubset_gen0Name(trac, gen0Nm, alias) RESULT(lerr) !=== TRACERS OF COMMON 1st GENERATION ANCESTOR 1044 TYPE(trac_type), ALLOCATABLE, INTENT(IN) :: trac(:) 1045 CHARACTER(LEN=*), INTENT(IN) :: gen0Nm 1046 TYPE(trac_type), ALLOCATABLE, INTENT(OUT) :: alias(:) 1047 CHARACTER(LEN=maxlen), ALLOCATABLE :: gen0N(:) 1048 lerr = getKey('gen0Name', gen0N, trac(:)%keys) 1049 alias = trac(strFind(delPhase(gen0N), gen0Nm)) 1050 lerr = indexUpdate(alias) 1051 END FUNCTION trSubset_gen0Name 1052 !============================================================================================================================== 1053 1054 1055 !============================================================================================================================== 1056 !=== UPDATE THE INDEXES iqParent, iqDescend AND iGeneration IN THE TRACERS DESCRIPTOR LIST "tr" (USEFULL FOR SUBSETS) ========= 1057 !============================================================================================================================== 1058 LOGICAL FUNCTION indexUpdate(tr) RESULT(lerr) 900 1059 TYPE(trac_type), INTENT(INOUT) :: tr(:) 901 902 !--- Update %iqParent, %iqDescen, %nqDescen, %nqChildren 903 CALL indexUpdate(tr) 904 905 !--- Extract some direct-access keys 906 ! DO iq = 1, SIZE(tr) 907 ! tr(iq)%keys%<key> = getKey_prv(it, "<key>", tr%keys, <default_value> ) 908 ! END DO 909 END SUBROUTINE setDirectKeys 910 !============================================================================================================================== 911 912 !============================================================================================================================== 913 LOGICAL FUNCTION dispTraSection(message, sname, modname) RESULT(lerr) 914 CHARACTER(LEN=*), INTENT(IN) :: message, sname, modname 915 INTEGER :: idb, iq, nq 916 INTEGER, ALLOCATABLE :: hadv(:), vadv(:) 917 CHARACTER(LEN=maxlen), ALLOCATABLE :: phas(:), prnt(:) 918 TYPE(trac_type), POINTER :: tm(:) 919 lerr = .FALSE. 920 idb = strIdx(dBase(:)%name, sname); IF(idb == 0) RETURN 921 tm => dBase(idb)%trac 922 nq = SIZE(tm) 923 !--- BEWARE ! Can't use the "getKeyByName" functions yet. 924 ! Names must first include the phases for tracers defined on multiple lines. 925 hadv = str2int(fgetKeys('hadv', tm(:)%keys, '10')) 926 vadv = str2int(fgetKeys('vadv', tm(:)%keys, '10')) 927 prnt = fgetKeys('parent',tm(:)%keys, '' ) 928 IF(getKey('phases', phas, ky=tm(:)%keys)) phas = fGetKeys('phase', tm(:)%keys, 'g') 929 CALL msg(TRIM(message)//':', modname) 930 IF(ALL(prnt == 'air')) THEN 931 IF(test(dispTable('iiiss', ['iq ','hadv ','vadv ','name ','phase '], cat(tm%name, phas), & 932 cat([(iq, iq=1, nq)], hadv, vadv), nColMax=maxTableWidth, nHead=2, sub=modname), lerr)) RETURN 933 ELSE IF(ALL(tm%iGeneration == -1)) THEN 934 IF(test(dispTable('iiisss', ['iq ','hadv ','vadv ','name ','parent','phase '], cat(tm%name, prnt, phas), & 935 cat([(iq, iq=1, nq)], hadv, vadv), nColMax=maxTableWidth, nHead=2, sub=modname), lerr)) RETURN 936 ELSE 937 IF(test(dispTable('iiissis', ['iq ','hadv ','vadv ','name ','parent','igen ','phase '], cat(tm%name, prnt, phas), & 938 cat([(iq, iq=1, nq)], hadv, vadv, tm%iGeneration), nColMax=maxTableWidth, nHead=2, sub=modname), lerr)) RETURN 939 END IF 940 END FUNCTION dispTraSection 941 !============================================================================================================================== 942 943 944 !============================================================================================================================== 945 !== CREATE A SCALAR ALIAS OF THE COMPONENT OF THE TRACERS DESCRIPTOR "t" NAMED "tname" ======================================== 946 !============================================================================================================================== 947 FUNCTION aliasTracer(tname, t) RESULT(out) 948 TYPE(trac_type), POINTER :: out 949 CHARACTER(LEN=*), INTENT(IN) :: tname 950 TYPE(trac_type), TARGET, INTENT(IN) :: t(:) 951 INTEGER :: it 952 it = strIdx(t(:)%name, tname) 953 out => NULL(); IF(it /= 0) out => t(it) 954 END FUNCTION aliasTracer 955 !============================================================================================================================== 956 957 958 !============================================================================================================================== 959 !=== FROM A LIST OF INDEXES OR NAMES, CREATE A SUBSET OF THE TRACERS DESCRIPTORS LIST "trac" ================================== 960 !============================================================================================================================== 961 FUNCTION trSubset_Indx(trac,idx) RESULT(out) 962 TYPE(trac_type), ALLOCATABLE :: out(:) 963 TYPE(trac_type), ALLOCATABLE, INTENT(IN) :: trac(:) 964 INTEGER, INTENT(IN) :: idx(:) 965 out = trac(idx) 966 CALL indexUpdate(out) 967 END FUNCTION trSubset_Indx 968 !------------------------------------------------------------------------------------------------------------------------------ 969 FUNCTION trSubset_Name(trac,nam) RESULT(out) 970 TYPE(trac_type), ALLOCATABLE :: out(:) 971 TYPE(trac_type), ALLOCATABLE, INTENT(IN) :: trac(:) 972 CHARACTER(LEN=*), INTENT(IN) :: nam(:) 973 out = trac(strIdx(trac(:)%name, nam)) 974 CALL indexUpdate(out) 975 END FUNCTION trSubset_Name 976 !============================================================================================================================== 977 978 979 !============================================================================================================================== 980 !=== CREATE THE SUBSET OF THE TRACERS DESCRIPTORS LIST "trac" HAVING THE FIRST GENERATION ANCESTOR NAMED "nam" ================ 981 !============================================================================================================================== 982 FUNCTION trSubset_gen0Name(trac,nam) RESULT(out) 983 TYPE(trac_type), ALLOCATABLE :: out(:) 984 TYPE(trac_type), ALLOCATABLE, INTENT(IN) :: trac(:) 985 CHARACTER(LEN=*), INTENT(IN) :: nam 986 out = trac(strFind(delPhase(trac(:)%gen0Name), nam)) 987 CALL indexUpdate(out) 988 END FUNCTION trSubset_gen0Name 989 !============================================================================================================================== 990 991 992 !============================================================================================================================== 993 !=== UPDATE THE INDEXES iqParent, iqDescend AND iGeneration IN THE TRACERS DESCRIPTOR LIST "tr" (USEFULL FOR SUBSETS) ========= 994 !============================================================================================================================== 995 SUBROUTINE indexUpdate(tr) 996 TYPE(trac_type), INTENT(INOUT) :: tr(:) 997 INTEGER :: iq, ig, igen, ngen, ix(SIZE(tr)) 998 tr(:)%iqParent = strIdx( tr(:)%name, tr(:)%parent ) !--- Parent index 999 DO iq = 1, SIZE(tr); CALL addKey_1('iqParent', int2str(tr(iq)%iqParent), tr(iq)%keys); END DO 1000 ngen = MAXVAL(tr(:)%iGeneration, MASK=.TRUE.) 1001 DO iq = 1, SIZE(tr) 1002 ig = tr(iq)%iGeneration 1003 IF(ALLOCATED(tr(iq)%iqDescen)) DEALLOCATE(tr(iq)%iqDescen) 1004 ALLOCATE(tr(iq)%iqDescen(0)) 1005 CALL idxAncestor(tr, ix, ig) !--- Ancestor of generation "ng" for each tr 1006 DO igen = ig+1, ngen 1007 tr(iq)%iqDescen = [tr(iq)%iqDescen, find(ix==iq .AND. tr%iGeneration==igen)] 1008 tr(iq)%nqDescen = SIZE(tr(iq)%iqDescen) 1009 IF(igen == ig+1) THEN 1010 tr(iq)%nqChildren = tr(iq)%nqDescen 1011 CALL addKey_1('nqChildren', int2str(tr(iq)%nqChildren), tr(iq)%keys) 1012 END IF 1060 INTEGER :: iq, jq, nq, ig, nGen 1061 INTEGER, ALLOCATABLE :: iqDescen(:), ix(:), iy(:) 1062 CHARACTER(LEN=maxlen), ALLOCATABLE :: tnames(:), parent(:) 1063 INTEGER, DIMENSION(SIZE(tr)) :: iqParent, iGen 1064 lerr = getKey('name', tnames, tr%keys); IF(lerr) RETURN !--- Names 1065 lerr = getKey('parent', parent, tr%keys); IF(lerr) RETURN !--- Parents 1066 nq = SIZE(tr) 1067 1068 !=== iqParent, iGeneration 1069 DO iq = 1, nq; iGen(iq) = 0; jq = iq 1070 iqParent(iq) = strIdx(tnames, parent(iq)) 1071 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) 1074 END DO 1075 1076 !=== nqChildren, iqDescen, nqDescen 1077 nGen = MAXVAL(iGen, MASK=.TRUE.) 1078 DO iq = 1, nq 1079 ix = [iq]; ALLOCATE(iqDescen(0)) 1080 DO ig = iGen(iq)+1, nGen 1081 iy = find(iqParent, ix); iqDescen = [iqDescen, iy]; ix = iy 1082 IF(ig /= iGen(iq)+1) CYCLE 1083 CALL addKey('nqChildren', SIZE(iqDescen), tr(iq)%keys) 1084 tr(iq)%nqChildren = SIZE(iqDescen) 1013 1085 END DO 1014 CALL addKey_1('iqDescen', strStack(int2str(tr(iq)%iqDescen)), tr(iq)%keys) 1015 CALL addKey_1('nqDescen', int2str(tr(iq)%nqDescen) , tr(iq)%keys) 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) 1090 DEALLOCATE(iqDescen) 1016 1091 END DO 1017 END SUBROUTINEindexUpdate1092 END FUNCTION indexUpdate 1018 1093 !============================================================================================================================== 1019 1094 … … 1024 1099 !=== * For each isotopes class, the <key>=<val> vector of each tracer is moved into the isotopes descriptor "isot" ==== 1025 1100 !=== NOTES: ==== 1026 !=== * Most of the "isot" components have been defined in the calling routine ( readIsotopes):====1101 !=== * Most of the "isot" components have been defined in the calling routine (processIsotopes): ==== 1027 1102 !=== parent, nzone, zone(:), niso, keys(:)%name, ntiso, trac(:), nphas, phas, iqIsoPha(:,:), itZonPhi(:,:) ==== 1028 1103 !=== * Same syntax for isotopes file and "tracer.def": a tracers section contains one line for each of its isotopes ==== … … 1032 1107 !=== * The routine gives an error if a required isotope is not available in the database stored in "fnam" ==== 1033 1108 !============================================================================================================================== 1034 LOGICAL FUNCTION readIsotopesFile _prv(fnam, isot) RESULT(lerr)1109 LOGICAL FUNCTION readIsotopesFile(fnam, isot) RESULT(lerr) 1035 1110 CHARACTER(LEN=*), INTENT(IN) :: fnam !--- Input file name 1036 1111 TYPE(isot_type), TARGET, INTENT(INOUT) :: isot(:) !--- Isotopes descriptors (field %parent must be defined!) … … 1049 1124 !--- READ THE FILE SECTIONS, ONE EACH PARENT TRACER 1050 1125 nb0 = SIZE(dBase, DIM=1)+1 !--- Next database element index 1051 IF(test(readSections(fnam,strStack(isot(:)%parent,'|')),lerr)) RETURN !--- Read sections, one each parent tracer1126 lerr = readSections(fnam,strStack(isot(:)%parent,'|')); IF(lerr) RETURN !--- Read sections, one each parent tracer 1052 1127 ndb = SIZE(dBase, DIM=1) !--- Current database size 1053 1128 DO idb = nb0, ndb … … 1067 1142 is = strIdx(isot(iis)%keys(:)%name, t%name) !--- Index in "isot(iis)%keys(:)%name" of isotope "t%name" 1068 1143 IF(is == 0) CYCLE 1069 IF(test(ANY(reduceExpr(t%keys%val, vals)), lerr)) RETURN!--- Reduce expressions ; detect non-numerical elements1144 lerr = ANY(reduceExpr(t%keys%val, vals)); IF(lerr) RETURN !--- Reduce expressions ; detect non-numerical elements 1070 1145 isot(iis)%keys(is)%key = t%keys%key 1071 1146 isot(iis)%keys(is)%val = vals … … 1073 1148 1074 1149 !--- CHECK FOR MISSING ISOTOPES (NO KEYS ALLOCATED) 1075 IF(test(checkList(isot(iis)%keys(:)%name, .NOT.[( ALLOCATED(isot(iis)%keys(is)%key), is=1, SIZE(isot(iis)%keys) )], & 1076 'Check file "'//TRIM(fnam)//'" in section "'//TRIM(dBase(idb)%name)//'"', 'isotopes', 'missing'), lerr)) RETURN 1150 lerr = checkList(isot(iis)%keys(:)%name, .NOT.[( ALLOCATED(isot(iis)%keys(is)%key), is=1, SIZE(isot(iis)%keys) )], & 1151 'Check file "'//TRIM(fnam)//'" in section "'//TRIM(dBase(idb)%name)//'"', 'isotopes', 'missing') 1152 IF(lerr) RETURN 1077 1153 END DO 1078 1154 … … 1109 1185 END DO 1110 1186 END DO 1111 IF(test(fmsg('Problem with the table content', modname, dispTable(prf, ttl, val, &1112 cat([(it,it=1,nt)]), rFmt='(EN8.4)', nColMax=maxTableWidth, nHead=2, sub=modname)), lerr)) RETURN1187 lerr = dispTable(prf, ttl, val, cat([(it,it=1,nt)]), rFmt='(EN8.4)', nColMax=maxTableWidth, nHead=2, sub=modname) 1188 IF(fmsg('Problem with the table content', modname, lerr)) RETURN 1113 1189 DEALLOCATE(ttl, val) 1114 1190 END DO … … 1116 1192 !------------------------------------------------------------------------------------------------------------------------------ 1117 1193 1118 END FUNCTION readIsotopesFile _prv1194 END FUNCTION readIsotopesFile 1119 1195 !============================================================================================================================== 1120 1196 … … 1124 1200 !=== * COMPUTE MOST OF THE RELATED QUANTITIES ("isot" COMPONENTS). === 1125 1201 !=== * COMPUTE FEW ISOTOPES-DEDICATED "trac" COMPONENTS === 1126 !=== * CALL readIsotopesFile _prv TO GET PHYSICAL QUANTITIES (<key>=<val> PAIRS)===1202 !=== * CALL readIsotopesFile TO GET PHYSICAL QUANTITIES (<key>=<val> PAIRS) === 1127 1203 !=== NOTE: THIS IS DONE HERE (IN A ROUTINE CALLED BY THE DYNAMIC), BECAUSE THE DYNAMIC NEEDS FEW PHYSICAL PARAMETERS. === 1128 1204 !============================================================================================================================== 1129 LOGICAL FUNCTION readIsotopesFile(iNames) RESULT(lerr)1205 LOGICAL FUNCTION processIsotopes(iNames) RESULT(lerr) 1130 1206 CHARACTER(LEN=maxlen), TARGET, OPTIONAL, INTENT(IN) :: iNames(:) 1131 1207 CHARACTER(LEN=maxlen), ALLOCATABLE :: p(:), str(:) !--- Temporary storage 1208 CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:), parent(:), dType(:), phase(:), gen0N(:) 1132 1209 CHARACTER(LEN=maxlen) :: iName, modname 1133 1210 CHARACTER(LEN=1) :: ph !--- Phase 1211 INTEGER, ALLOCATABLE :: iGen(:) 1134 1212 INTEGER :: ic, ip, iq, it, iz 1135 1213 LOGICAL, ALLOCATABLE :: ll(:) !--- Mask 1136 1214 TYPE(trac_type), POINTER :: t(:), t1 1137 1215 TYPE(isot_type), POINTER :: i 1216 1138 1217 lerr = .FALSE. 1139 1218 modname = 'readIsotopesFile' … … 1141 1220 t => tracers 1142 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 1228 1143 1229 !--- GET FROM "tracers" THE FULL LIST OF AVAILABLE ISOTOPES CLASSES 1144 p = PACK(delPhase( t%parent), MASK = t%type=='tracer' .AND. t%iGeneration==1)1230 p = PACK(delPhase(parent), MASK = dType=='tracer' .AND. iGen==1) 1145 1231 CALL strReduce(p, nbIso) 1146 1232 … … 1148 1234 IF(PRESENT(iNames)) THEN 1149 1235 DO it = 1, SIZE(iNames) 1150 IF(test(fmsg('No isotopes class "'//TRIM(iNames(it))//'" found among tracers', modname, ALL(p /= iNames(it))), lerr)) RETURN 1236 lerr = ALL(p /= iNames(it)) 1237 IF(fmsg('No isotopes class "'//TRIM(iNames(it))//'" found among tracers', modname, lerr)) RETURN 1151 1238 END DO 1152 1239 p = iNames; nbIso = SIZE(p) … … 1164 1251 1165 1252 !=== Isotopes children of tracer "iname": mask, names, number (same for each phase of "iname") 1166 ll = t(:)%type=='tracer' .AND. delPhase(t(:)%parent) == iname .AND. t(:)%phase == 'g'1167 str = PACK(delPhase(t (:)%name), MASK = ll)!--- Effectively found isotopes 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" 1168 1255 i%niso = SIZE(str) !--- Number of "effectively found isotopes of "iname" 1169 1256 ALLOCATE(i%keys(i%niso)) … … 1171 1258 1172 1259 !=== Geographic tagging tracers descending on tracer "iname": mask, names, number 1173 ll = t(:)%type=='tag' .AND. delPhase(t(:)%gen0Name) == iname .AND. t(:)%iGeneration == 21174 i%zone = PACK(strTail(t (:)%name,'_',.TRUE.), MASK = ll)!--- Tagging zones names for isotopes category "iname"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" 1175 1262 CALL strReduce(i%zone) 1176 1263 i%nzone = SIZE(i%zone) !--- Tagging zones number for isotopes category "iname" … … 1178 1265 !=== Geographic tracers of the isotopes children of tracer "iname" (same for each phase of "iname") 1179 1266 ! NOTE: One might like to create a similar variable for 2nd generation tagging tracers (tagging the gen1 tracers) 1180 str = PACK(delPhase(t (:)%name), MASK=ll)1267 str = PACK(delPhase(tname), MASK=ll) 1181 1268 CALL strReduce(str) 1182 1269 i%ntiso = i%niso + SIZE(str) !--- Number of isotopes + their geographic tracers [ntiso] … … 1205 1292 i%iqIsoPha = RESHAPE( [( (strIdx(t%name, addPhase(i%trac(it),i%phase(ip:ip))), it=1, i%ntiso), ip=1, i%nphas)], & 1206 1293 [i%ntiso, i%nphas] ) 1294 !=== Table used to get iq (index in dyn array, size nqtot) from the water and isotope and phase indexes ; the full isotopes list 1295 ! (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] ) 1207 1298 !=== Table used to get ix (index in tagging tracers isotopes list, size ntiso) from the zone and isotope indexes 1208 1299 i%itZonIso = RESHAPE( [( (strIdx(i%trac(:), TRIM(i%trac(it))//'_'//TRIM(i%zone(iz))), iz=1, i%nzone), it=1, i%niso )], & … … 1211 1302 1212 1303 !=== READ PHYSICAL PARAMETERS FROM isoFile FILE 1213 IF(test(readIsotopesFile_prv(isoFile, isotopes), lerr)) RETURN 1304 ! lerr = readIsotopesFile(isoFile, isotopes); IF(lerr) RETURN! on commente pour ne pas chercher isotopes_params.def 1305 1306 !--- GET THE isoCheck ENTRY FROM THE *.DEF FILES (MIGHT BE CHANGED TO A CLASS-DEPENDANT KEYWORD) 1307 CALL get_in('ok_iso_verif', isoCheck, .TRUE.) 1214 1308 1215 1309 !=== CHECK CONSISTENCY 1216 IF(test(testIsotopes(), lerr)) RETURN1217 1218 !=== SELECT FIRST ISOTOPES CLASS OR, IF POSSIBLE, WATERCLASS1219 IF( .NOT.test(isoSelect(1, .TRUE.), lerr)) THEN; IF(isotope%parent == 'H2O') iH2O = ixIso; END IF1310 lerr = testIsotopes(); IF(lerr) RETURN 1311 1312 !=== 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 1220 1314 1221 1315 CONTAINS … … 1224 1318 LOGICAL FUNCTION testIsotopes() RESULT(lerr) !--- MAKE SURE MEMBERS OF AN ISOTOPES FAMILY ARE PRESENT IN THE SAME PHASES 1225 1319 !------------------------------------------------------------------------------------------------------------------------------ 1226 INTEGER :: ix, it, ip, np, iz, nz 1320 INTEGER :: ix, it, ip, np, iz, nz, npha, nzon 1227 1321 TYPE(isot_type), POINTER :: i 1228 1322 DO ix = 1, nbIso 1229 1323 i => isotopes(ix) 1230 1324 !--- Check whether each isotope and tagging isotopic tracer is present in the same number of phases 1231 DO it = 1, i%ntiso 1232 np = SUM([(COUNT(tracers(:)%name == addPhase(i%trac(it), i%phase(ip:ip))), ip=1, i%nphas)]) 1233 IF(test(fmsg(TRIM(int2str(np))//' phases instead of '//TRIM(int2str(i%nphas))//' for '//TRIM(i%trac(it)), & 1234 modname, np /= i%nphas), lerr)) RETURN 1325 DO it = 1, i%ntiso; npha = i%nphas 1326 np = SUM([(COUNT(tracers(:)%name == addPhase(i%trac(it), i%phase(ip:ip))), ip=1, npha)]) 1327 lerr = np /= npha 1328 CALL msg(TRIM(int2str(np))//' phases instead of '//TRIM(int2str(npha))//' for '//TRIM(i%trac(it)), modname, lerr) 1329 IF(lerr) RETURN 1235 1330 END DO 1236 DO it = 1, i%niso 1237 nz = SUM([(COUNT(i%trac == TRIM(i%trac(it))//'_'//i%zone(iz)), iz=1, i%nzone)]) 1238 IF(test(fmsg(TRIM(int2str(nz))//' tagging zones instead of '//TRIM(int2str(i%nzone))//' for '//TRIM(i%trac(it)), & 1239 modname, nz /= i%nzone), lerr)) RETURN 1331 DO it = 1, i%niso; nzon = i%nzone 1332 nz = SUM([(COUNT(i%trac == TRIM(i%trac(it))//'_'//i%zone(iz)), iz=1, nzon)]) 1333 lerr = nz /= nzon 1334 CALL msg(TRIM(int2str(nz))//' tagging zones instead of '//TRIM(int2str(nzon))//' for '//TRIM(i%trac(it)), modname, lerr) 1335 IF(lerr) RETURN 1240 1336 END DO 1241 1337 END DO … … 1243 1339 !------------------------------------------------------------------------------------------------------------------------------ 1244 1340 1245 END FUNCTION readIsotopesFile1341 END FUNCTION processIsotopes 1246 1342 !============================================================================================================================== 1247 1343 … … 1259 1355 lV = .FALSE.; IF(PRESENT(lVerbose)) lV = lVerbose 1260 1356 iIso = strIdx(isotopes(:)%parent, iName) 1261 IF(test(iIso == 0, lerr)) THEN 1357 lerr = iIso == 0 1358 IF(lerr) THEN 1262 1359 niso = 0; ntiso = 0; nzone = 0; nphas = 0; isoCheck=.FALSE. 1263 1360 CALL msg('no isotope family named "'//TRIM(iName)//'"', ll=lV) … … 1287 1384 itZonIso => isotope%itZonIso; isoCheck = isotope%check 1288 1385 iqIsoPha => isotope%iqIsoPha 1386 iqWIsoPha => isotope%iqWIsoPha 1289 1387 END FUNCTION isoSelectByIndex 1290 1388 !============================================================================================================================== … … 1294 1392 !=== ADD THE <key>=<val> PAIR TO THE "ky[(:)]" KEY[S] DESCRIPTOR[S] OR THE <key>=<val(:)> PAIRS TO THE "ky(:)" KEYS DESCRIPTORS 1295 1393 !============================================================================================================================== 1296 SUBROUTINE addKey_ 1(key,val, ky, lOverWrite)1297 CHARACTER(LEN=*), INTENT(IN) :: key, val1394 SUBROUTINE addKey_s11(key, sval, ky, lOverWrite) 1395 CHARACTER(LEN=*), INTENT(IN) :: key, sval 1298 1396 TYPE(keys_type), INTENT(INOUT) :: ky 1299 1397 LOGICAL, OPTIONAL, INTENT(IN) :: lOverWrite … … 1305 1403 IF(.NOT.ALLOCATED(ky%key)) THEN 1306 1404 ALLOCATE(ky%key(1)); ky%key(1)=key 1307 ALLOCATE(ky%val(1)); ky%val(1)= val1405 ALLOCATE(ky%val(1)); ky%val(1)=sval 1308 1406 RETURN 1309 1407 END IF … … 1311 1409 IF(iky == 0) THEN 1312 1410 nky = SIZE(ky%key) 1313 ALLOCATE(k(nky+1)); k(1:nky) = ky%key; k(nky+1) = key; ky%key = k1314 ALLOCATE(v(nky+1)); v(1:nky) = ky%val; v(nky+1) = val; ky%val = v1411 ALLOCATE(k(nky+1)); k(1:nky) = ky%key; k(nky+1) = key; ky%key = k 1412 ALLOCATE(v(nky+1)); v(1:nky) = ky%val; v(nky+1) = sval; ky%val = v 1315 1413 ELSE IF(lo) THEN 1316 ky%key(iky) = key; ky%val(iky) = val1414 ky%key(iky) = key; ky%val(iky) = sval 1317 1415 END IF 1318 END SUBROUTINE addKey_1 1319 !============================================================================================================================== 1320 SUBROUTINE addKey_m(key, val, ky, lOverWrite) 1321 CHARACTER(LEN=*), INTENT(IN) :: key, val 1416 END SUBROUTINE addKey_s11 1417 !============================================================================================================================== 1418 SUBROUTINE addKey_i11(key, ival, ky, lOverWrite) 1419 CHARACTER(LEN=*), INTENT(IN) :: key 1420 INTEGER, INTENT(IN) :: ival 1421 TYPE(keys_type), INTENT(INOUT) :: ky 1422 LOGICAL, OPTIONAL, INTENT(IN) :: lOverWrite 1423 !------------------------------------------------------------------------------------------------------------------------------ 1424 CALL addKey_s11(key, int2str(ival), ky, lOverWrite) 1425 END SUBROUTINE addKey_i11 1426 !============================================================================================================================== 1427 SUBROUTINE addKey_r11(key, rval, ky, lOverWrite) 1428 CHARACTER(LEN=*), INTENT(IN) :: key 1429 REAL, INTENT(IN) :: rval 1430 TYPE(keys_type), INTENT(INOUT) :: ky 1431 LOGICAL, OPTIONAL, INTENT(IN) :: lOverWrite 1432 !------------------------------------------------------------------------------------------------------------------------------ 1433 CALL addKey_s11(key, real2str(rval), ky, lOverWrite) 1434 END SUBROUTINE addKey_r11 1435 !============================================================================================================================== 1436 SUBROUTINE addKey_l11(key, lval, ky, lOverWrite) 1437 CHARACTER(LEN=*), INTENT(IN) :: key 1438 LOGICAL, INTENT(IN) :: lval 1439 TYPE(keys_type), INTENT(INOUT) :: ky 1440 LOGICAL, OPTIONAL, INTENT(IN) :: lOverWrite 1441 !------------------------------------------------------------------------------------------------------------------------------ 1442 CALL addKey_s11(key, bool2str(lval), ky, lOverWrite) 1443 END SUBROUTINE addKey_l11 1444 !============================================================================================================================== 1445 !============================================================================================================================== 1446 SUBROUTINE addKey_s1m(key, sval, ky, lOverWrite) 1447 CHARACTER(LEN=*), INTENT(IN) :: key, sval 1322 1448 TYPE(keys_type), INTENT(INOUT) :: ky(:) 1323 1449 LOGICAL, OPTIONAL, INTENT(IN) :: lOverWrite 1324 1450 !------------------------------------------------------------------------------------------------------------------------------ 1325 1451 INTEGER :: itr 1326 DO itr = 1, SIZE(ky) 1327 CALL addKey_1(key, val, ky(itr), lOverWrite) 1328 END DO 1329 END SUBROUTINE addKey_m 1330 !============================================================================================================================== 1331 SUBROUTINE addKey_mm(key, val, ky, lOverWrite) 1332 CHARACTER(LEN=*), INTENT(IN) :: key, val(:) 1452 DO itr = 1, SIZE(ky); CALL addKey_s11(key, sval, ky(itr), lOverWrite); END DO 1453 END SUBROUTINE addKey_s1m 1454 !============================================================================================================================== 1455 SUBROUTINE addKey_i1m(key, ival, ky, lOverWrite) 1456 CHARACTER(LEN=*), INTENT(IN) :: key 1457 INTEGER, INTENT(IN) :: ival 1333 1458 TYPE(keys_type), INTENT(INOUT) :: ky(:) 1334 1459 LOGICAL, OPTIONAL, INTENT(IN) :: lOverWrite 1335 1460 !------------------------------------------------------------------------------------------------------------------------------ 1336 1461 INTEGER :: itr 1337 DO itr = 1, SIZE(ky); CALL addKey_1(key, val(itr), ky(itr), lOverWrite); END DO 1338 END SUBROUTINE addKey_mm 1462 DO itr = 1, SIZE(ky); CALL addKey_s11(key, int2str(ival), ky(itr), lOverWrite); END DO 1463 END SUBROUTINE addKey_i1m 1464 !============================================================================================================================== 1465 SUBROUTINE addKey_r1m(key, rval, ky, lOverWrite) 1466 CHARACTER(LEN=*), INTENT(IN) :: key 1467 REAL, INTENT(IN) :: rval 1468 TYPE(keys_type), INTENT(INOUT) :: ky(:) 1469 LOGICAL, OPTIONAL, INTENT(IN) :: lOverWrite 1470 !------------------------------------------------------------------------------------------------------------------------------ 1471 INTEGER :: itr 1472 DO itr = 1, SIZE(ky); CALL addKey_s11(key, real2str(rval), ky(itr), lOverWrite); END DO 1473 END SUBROUTINE addKey_r1m 1474 !============================================================================================================================== 1475 SUBROUTINE addKey_l1m(key, lval, ky, lOverWrite) 1476 CHARACTER(LEN=*), INTENT(IN) :: key 1477 LOGICAL, INTENT(IN) :: lval 1478 TYPE(keys_type), INTENT(INOUT) :: ky(:) 1479 LOGICAL, OPTIONAL, INTENT(IN) :: lOverWrite 1480 !------------------------------------------------------------------------------------------------------------------------------ 1481 INTEGER :: itr 1482 DO itr = 1, SIZE(ky); CALL addKey_s11(key, bool2str(lval), ky(itr), lOverWrite); END DO 1483 END SUBROUTINE addKey_l1m 1484 !============================================================================================================================== 1485 !============================================================================================================================== 1486 SUBROUTINE addKey_smm(key, sval, ky, lOverWrite) 1487 CHARACTER(LEN=*), INTENT(IN) :: key, sval(:) 1488 TYPE(keys_type), INTENT(INOUT) :: ky(:) 1489 LOGICAL, OPTIONAL, INTENT(IN) :: lOverWrite 1490 !------------------------------------------------------------------------------------------------------------------------------ 1491 INTEGER :: itr 1492 DO itr = 1, SIZE(ky); CALL addKey_s11(key, sval(itr), ky(itr), lOverWrite); END DO 1493 END SUBROUTINE addKey_smm 1494 !============================================================================================================================== 1495 SUBROUTINE addKey_imm(key, ival, ky, lOverWrite) 1496 CHARACTER(LEN=*), INTENT(IN) :: key 1497 INTEGER, INTENT(IN) :: ival(:) 1498 TYPE(keys_type), INTENT(INOUT) :: ky(:) 1499 LOGICAL, OPTIONAL, INTENT(IN) :: lOverWrite 1500 !------------------------------------------------------------------------------------------------------------------------------ 1501 INTEGER :: itr 1502 DO itr = 1, SIZE(ky); CALL addKey_s11(key, int2str(ival(itr)), ky(itr), lOverWrite); END DO 1503 END SUBROUTINE addKey_imm 1504 !============================================================================================================================== 1505 SUBROUTINE addKey_rmm(key, rval, ky, lOverWrite) 1506 CHARACTER(LEN=*), INTENT(IN) :: key 1507 REAL, INTENT(IN) :: rval(:) 1508 TYPE(keys_type), INTENT(INOUT) :: ky(:) 1509 LOGICAL, OPTIONAL, INTENT(IN) :: lOverWrite 1510 !------------------------------------------------------------------------------------------------------------------------------ 1511 INTEGER :: itr 1512 DO itr = 1, SIZE(ky); CALL addKey_s11(key, real2str(rval(itr)), ky(itr), lOverWrite); END DO 1513 END SUBROUTINE addKey_rmm 1514 !============================================================================================================================== 1515 SUBROUTINE addKey_lmm(key, lval, ky, lOverWrite) 1516 CHARACTER(LEN=*), INTENT(IN) :: key 1517 LOGICAL, INTENT(IN) :: lval(:) 1518 TYPE(keys_type), INTENT(INOUT) :: ky(:) 1519 LOGICAL, OPTIONAL, INTENT(IN) :: lOverWrite 1520 !------------------------------------------------------------------------------------------------------------------------------ 1521 INTEGER :: itr 1522 DO itr = 1, SIZE(ky); CALL addKey_s11(key, bool2str(lval(itr)), ky(itr), lOverWrite); END DO 1523 END SUBROUTINE addKey_lmm 1339 1524 !============================================================================================================================== 1340 1525 … … 1353 1538 DO ik = 1, SIZE(t(jd)%keys%key) 1354 1539 CALL get_in(t(jd)%keys%key(ik), val, '*none*') 1355 IF(val /= '*none*') CALL addKey _1(t(jd)%keys%key(ik), val, t(jd)%keys, .TRUE.)1540 IF(val /= '*none*') CALL addKey(t(jd)%keys%key(ik), val, t(jd)%keys, .TRUE.) 1356 1541 END DO 1357 1542 END SUBROUTINE addKeysFromDef … … 1387 1572 1388 1573 !============================================================================================================================== 1389 !================ GET THE VALUE OF A KEY FROM A "keys_type" DERIVED TYPE ; THE RESULT IS THE RETURNED VALUE =================== 1390 !============================================================================================================================== 1391 CHARACTER(LEN=maxlen) FUNCTION fgetKeyIdx_s1(itr, keyn, ky, def_val, lerr) RESULT(val) 1574 !=== INTERNAL FUNCTION: GET THE VALUE OF A KEY FOR "itr"th TRACER FROM A "keys_type" DERIVED TYPE AND RETURN THE RESULT === 1575 !=== IF keyn CONTAINS SEVERAL ELEMENTS, TRY WITH EACH ELEMENT ONE AFTER THE OTHER === 1576 !============================================================================================================================== 1577 CHARACTER(LEN=maxlen) FUNCTION fgetKeyIdx(itr, keyn, ky, lerr) RESULT(val) 1392 1578 INTEGER, INTENT(IN) :: itr 1393 CHARACTER(LEN=*), INTENT(IN) :: keyn 1579 CHARACTER(LEN=*), INTENT(IN) :: keyn(:) 1394 1580 TYPE(keys_type), INTENT(IN) :: ky(:) 1395 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: def_val1396 1581 LOGICAL, OPTIONAL, INTENT(OUT) :: lerr 1397 1582 !------------------------------------------------------------------------------------------------------------------------------ 1583 INTEGER :: ik 1584 LOGICAL :: ler 1585 ler = .TRUE. 1586 DO ik = 1, SIZE(keyn) 1587 CALL getKeyIdx(keyn(ik)); IF(.NOT.ler) EXIT 1588 END DO 1589 IF(PRESENT(lerr)) lerr = ler 1590 1591 CONTAINS 1592 1593 SUBROUTINE getKeyIdx(keyn) 1594 CHARACTER(LEN=*), INTENT(IN) :: keyn 1595 !------------------------------------------------------------------------------------------------------------------------------ 1398 1596 INTEGER :: iky 1399 LOGICAL :: ler1400 1597 iky = 0; val = '' 1401 IF(.NOT.test(itr <= 0 .OR. itr > SIZE(ky), ler)) iky = strIdx(ky(itr)%key(:), keyn) !--- Correct index 1402 IF(.NOT.test(iky == 0, ler)) val = ky(itr)%val(iky) !--- Found key 1403 IF(iky == 0) THEN 1404 IF(.NOT.test(.NOT.PRESENT(def_val), ler)) val = def_val !--- Default value 1405 END IF 1406 IF(PRESENT(lerr)) lerr = ler 1407 END FUNCTION fgetKeyIdx_s1 1408 !============================================================================================================================== 1409 CHARACTER(LEN=maxlen) FUNCTION fgetKeyNam_s1(tname, keyn, ky, def_val, lerr) RESULT(val) 1410 CHARACTER(LEN=*), INTENT(IN) :: tname, keyn 1411 TYPE(keys_type), INTENT(IN) :: ky(:) 1412 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: def_val 1413 LOGICAL, OPTIONAL, INTENT(OUT) :: lerr 1414 !------------------------------------------------------------------------------------------------------------------------------ 1415 val = fgetKeyIdx_s1(strIdx(ky(:)%name, tname), keyn, ky, def_val, lerr) 1416 END FUNCTION fgetKeyNam_s1 1417 !============================================================================================================================== 1418 FUNCTION fgetKeys(keyn, ky, def_val, lerr) RESULT(val) 1419 CHARACTER(LEN=maxlen), ALLOCATABLE :: val(:) 1420 CHARACTER(LEN=*), INTENT(IN) :: keyn 1421 TYPE(keys_type), INTENT(IN) :: ky(:) 1422 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: def_val 1423 LOGICAL, OPTIONAL, INTENT(OUT) :: lerr 1424 !------------------------------------------------------------------------------------------------------------------------------ 1425 LOGICAL :: ler(SIZE(ky)) 1426 INTEGER :: it 1427 val = [(fgetKeyIdx_s1(it, keyn, ky, def_val, ler(it)), it = 1, SIZE(ky))] 1428 IF(PRESENT(lerr)) lerr = ANY(ler) 1429 END FUNCTION fgetKeys 1430 !============================================================================================================================== 1431 1432 1433 !============================================================================================================================== 1434 !========== GET THE VALUE OF A KEY FROM A "keys_type" DERIVED TYPE ; THE RETURNED VALUE IS THE ERROR CODE ============== 1435 !========== The key "keyn" is searched in: 1) "ky(:)%name" (if given) ============== 1436 !========== 2) "tracers(:)%name" ============== 1437 !========== 3) "isotope%keys(:)%name" ============== 1438 !========== for the tracer[s] "tname[(:)]" (if given) or all the available tracers from the used set otherwise. ============== 1439 !========== The type of the returned value(s) can be string, integer or real, scalar or vector ============== 1440 !============================================================================================================================== 1441 LOGICAL FUNCTION getKeyByName_s1(keyn, val, tname, ky) RESULT(lerr) 1598 ler = itr <= 0 .OR. itr > SIZE(ky); IF(ler) RETURN 1599 iky = strIdx(ky(itr)%key(:), keyn) 1600 ler = iky == 0; IF(ler) RETURN 1601 val = ky(itr)%val(iky) 1602 END SUBROUTINE getKeyIdx 1603 1604 END FUNCTION fgetKeyIdx 1605 !============================================================================================================================== 1606 1607 1608 !============================================================================================================================== 1609 !=== GET KEYS VALUES FROM TRACERS INDICES === 1610 !============================================================================================================================== 1611 !=== TRY TO GET THE KEY NAMED "key" FOR THE "itr"th TRACER IN: === 1612 !=== * ARGUMENT "ky" DATABASE IF SPECIFIED ; OTHERWISE: === 1613 !=== * IN INTERNAL TRACERS DATABASE "tracers(:)%keys" (IF UNFOUND, IN INTERNAL ISOTOPES DATABASE "isotope%keys(:)") === 1614 !=== THE RETURNED VALUE (STRING, AN INTEGER, A REAL OR A LOGICAL) CAN BE EITHER: === 1615 !=== * A SCALAR === 1616 !=== * A VECTOR, WHICH IS THE FOUND VALUE PARSED WITH THE SEPARATOR "," === 1617 !=== === 1618 !=== SYNTAX: lerr = getKeyByIndex_{sirl}{1m}{1m}1(keyn[(:)], val[(:)], itr[, ky(:)] [, def][, lDisp]) === 1619 !============================================================================================================================== 1620 !=== IF "itr" IS NOT PRESENT, VALUES FOR ALL THE TRACERS OF THE SELECTED DATABASE ARE STORED IN THE VECTOR "val(:)" === 1621 !=== THE NAME OF THE TRACERS FOUND IN THE EFFECTIVELY USED DATABASE CAN BE RETURNED OPTIONALLY IN "nam(:)" === 1622 !=== SYNTAX lerr = getKeyByIndex_{sirl}{1m}mm (keyn[(:)], val (:) [, ky(:)][, nam(:)][, def][, lDisp]) === 1623 !============================================================================================================================== 1624 LOGICAL FUNCTION getKeyByIndex_s111(keyn, val, itr, ky, def, lDisp) RESULT(lerr) 1442 1625 CHARACTER(LEN=*), INTENT(IN) :: keyn 1443 1626 CHARACTER(LEN=maxlen), INTENT(OUT) :: val 1444 CHARACTER(LEN=*), INTENT(IN) :: tname1627 INTEGER, INTENT(IN) :: itr 1445 1628 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1446 !------------------------------------------------------------------------------------------------------------------------------ 1447 CHARACTER(LEN=maxlen) :: tnam 1448 tnam = strHead(delPhase(tname),'_',.TRUE.) !--- Remove phase and tag 1449 IF(PRESENT(ky)) THEN !=== KEY FROM "ky" 1450 val = fgetKeyNam_s1(tname, keyn, ky, lerr=lerr) !--- "ky" and "tname" 1451 IF( lerr ) val = fgetKeyNam_s1(tnam, keyn, ky, lerr=lerr) !--- "ky" and "tnam" 1452 ELSE 1453 IF( .NOT.test(.NOT.ALLOCATED(tracers ), lerr)) lerr = SIZE(tracers ) == 0 !=== KEY FROM "tracers" 1454 IF(.NOT.lerr) THEN 1455 val = fgetKeyNam_s1(tname, keyn, tracers%keys, lerr=lerr) !--- "ky" and "tname" 1456 IF(lerr) val = fgetKeyNam_s1(tnam, keyn, tracers%keys, lerr=lerr) !--- "ky" and "tnam" 1457 END IF 1458 IF(lerr.AND..NOT.test(.NOT.ALLOCATED(isotopes), lerr)) lerr = SIZE(isotopes) == 0 !=== KEY FROM "isotope" 1459 IF(.NOT.lerr) THEN 1460 val = fgetKeyNam_s1(tname, keyn, isotope%keys, lerr=lerr) !--- "ky" and "tname" 1461 IF(lerr) val = fgetKeyNam_s1(tnam, keyn, isotope%keys, lerr=lerr) !--- "ky" and "tnam" 1462 END IF 1629 CHARACTER(LEN=*),OPTIONAL, INTENT(IN) :: def 1630 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1631 lerr = getKeyByIndex_sm11([keyn], val, itr, ky, def, lDisp) 1632 END FUNCTION getKeyByIndex_s111 1633 !============================================================================================================================== 1634 LOGICAL FUNCTION getKeyByIndex_i111(keyn, val, itr, ky, def, lDisp) RESULT(lerr) 1635 CHARACTER(LEN=*), INTENT(IN) :: keyn 1636 INTEGER, INTENT(OUT) :: val 1637 INTEGER, INTENT(IN) :: itr 1638 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1639 INTEGER, OPTIONAL, INTENT(IN) :: def 1640 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1641 lerr = getKeyByIndex_im11([keyn], val, itr, ky, def, lDisp) 1642 END FUNCTION getKeyByIndex_i111 1643 !============================================================================================================================== 1644 LOGICAL FUNCTION getKeyByIndex_r111(keyn, val, itr, ky, def, lDisp) RESULT(lerr) 1645 CHARACTER(LEN=*), INTENT(IN) :: keyn 1646 REAL , INTENT(OUT) :: val 1647 INTEGER, INTENT(IN) :: itr 1648 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1649 REAL, OPTIONAL, INTENT(IN) :: def 1650 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1651 lerr = getKeyByIndex_rm11([keyn], val, itr, ky, def, lDisp) 1652 END FUNCTION getKeyByIndex_r111 1653 !============================================================================================================================== 1654 LOGICAL FUNCTION getKeyByIndex_l111(keyn, val, itr, ky, def, lDisp) RESULT(lerr) 1655 CHARACTER(LEN=*), INTENT(IN) :: keyn 1656 LOGICAL, INTENT(OUT) :: val 1657 INTEGER, INTENT(IN) :: itr 1658 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1659 LOGICAL, OPTIONAL, INTENT(IN) :: def 1660 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1661 lerr = getKeyByIndex_lm11([keyn], val, itr, ky, def, lDisp) 1662 END FUNCTION getKeyByIndex_l111 1663 !============================================================================================================================== 1664 !============================================================================================================================== 1665 LOGICAL FUNCTION getKeyByIndex_sm11(keyn, val, itr, ky, def, lDisp) RESULT(lerr) 1666 CHARACTER(LEN=*), INTENT(IN) :: keyn(:) 1667 CHARACTER(LEN=maxlen), INTENT(OUT) :: val 1668 INTEGER, INTENT(IN) :: itr 1669 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1670 CHARACTER(LEN=*),OPTIONAL, INTENT(IN) :: def 1671 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1672 !------------------------------------------------------------------------------------------------------------------------------ 1673 CHARACTER(LEN=maxlen) :: s 1674 LOGICAL :: lD 1675 lD = .TRUE.; IF(PRESENT(lDisp)) lD = lDisp 1676 s = 'key "'//TRIM(strStack(keyn, '/'))//'" for tracer nr. '//TRIM(int2str(itr)) 1677 lerr = .TRUE. 1678 IF(lerr .AND. PRESENT(ky)) val = fgetKey(ky) !--- "ky" 1679 IF(lerr .AND. ALLOCATED (tracers)) val = fgetKey(tracers(:)%keys) !--- "tracers" 1680 IF(lerr .AND. ASSOCIATED(isotope)) val = fgetKey(isotope%keys(:)) !--- "isotope" 1681 IF(lerr .AND. PRESENT(def)) THEN 1682 val = def; lerr = .NOT.PRESENT(def) 1683 CALL msg('Using defaut value of '//TRIM(s)//': '//TRIM(def), modname, lD) 1463 1684 END IF 1464 END FUNCTION getKeyByName_s1 1465 !============================================================================================================================== 1466 LOGICAL FUNCTION getKeyByName_s1m(keyn, val, tname, ky) RESULT(lerr) 1685 CALL msg('No '//TRIM(s)//' or out of bounds index', modname, lD .AND. lerr) 1686 1687 CONTAINS 1688 1689 CHARACTER(LEN=maxlen) FUNCTION fgetKey(ky) RESULT(val) 1690 TYPE(keys_type), INTENT(IN) :: ky(:) 1691 lerr = SIZE(ky) == 0; IF(lerr) RETURN 1692 val = fgetKeyIdx(itr, keyn(:), ky, lerr) 1693 END FUNCTION fgetKey 1694 1695 END FUNCTION getKeyByIndex_sm11 1696 !============================================================================================================================== 1697 LOGICAL FUNCTION getKeyByIndex_im11(keyn, val, itr, ky, def, lDisp) RESULT(lerr) 1698 CHARACTER(LEN=*), INTENT(IN) :: keyn(:) 1699 INTEGER, INTENT(OUT) :: val 1700 INTEGER, INTENT(IN) :: itr 1701 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1702 INTEGER, OPTIONAL, INTENT(IN) :: def 1703 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1704 !------------------------------------------------------------------------------------------------------------------------------ 1705 CHARACTER(LEN=maxlen) :: sval, s 1706 IF( PRESENT(def)) lerr = getKeyByIndex_sm11(keyn, sval, itr, ky, int2str(def), lDisp) 1707 IF(.NOT.PRESENT(def)) lerr = getKeyByIndex_sm11(keyn, sval, itr, ky, lDisp=lDisp) 1708 IF(lerr) RETURN 1709 val = str2int(sval) 1710 lerr = val == -HUGE(1) 1711 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of tracer nr. '//TRIM(int2str(itr))//' is not' 1712 CALL msg(TRIM(s)//' an integer: '//TRIM(sval), modname, lerr) 1713 END FUNCTION getKeyByIndex_im11 1714 !============================================================================================================================== 1715 LOGICAL FUNCTION getKeyByIndex_rm11(keyn, val, itr, ky, def, lDisp) RESULT(lerr) 1716 CHARACTER(LEN=*), INTENT(IN) :: keyn(:) 1717 REAL , INTENT(OUT) :: val 1718 INTEGER, INTENT(IN) :: itr 1719 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1720 REAL, OPTIONAL, INTENT(IN) :: def 1721 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1722 !------------------------------------------------------------------------------------------------------------------------------ 1723 CHARACTER(LEN=maxlen) :: sval, s 1724 IF( PRESENT(def)) lerr = getKeyByIndex_sm11(keyn, sval, itr, ky, real2str(def), lDisp) 1725 IF(.NOT.PRESENT(def)) lerr = getKeyByIndex_sm11(keyn, sval, itr, ky, lDisp=lDisp) 1726 IF(lerr) RETURN 1727 val = str2real(sval) 1728 lerr = val == -HUGE(1.) 1729 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of tracer nr. '//TRIM(int2str(itr))//' is not' 1730 CALL msg(TRIM(s)//' a real: '//TRIM(sval), modname, lerr) 1731 END FUNCTION getKeyByIndex_rm11 1732 !============================================================================================================================== 1733 LOGICAL FUNCTION getKeyByIndex_lm11(keyn, val, itr, ky, def, lDisp) RESULT(lerr) 1734 CHARACTER(LEN=*), INTENT(IN) :: keyn(:) 1735 LOGICAL, INTENT(OUT) :: val 1736 INTEGER, INTENT(IN) :: itr 1737 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1738 LOGICAL, OPTIONAL, INTENT(IN) :: def 1739 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1740 !------------------------------------------------------------------------------------------------------------------------------ 1741 CHARACTER(LEN=maxlen) :: sval, s 1742 INTEGER :: ival 1743 IF( PRESENT(def)) lerr = getKeyByIndex_sm11(keyn, sval, itr, ky, bool2str(def), lDisp) 1744 IF(.NOT.PRESENT(def)) lerr = getKeyByIndex_sm11(keyn, sval, itr, ky, lDisp=lDisp) 1745 IF(lerr) RETURN 1746 ival = str2bool(sval) 1747 lerr = ival == -1 1748 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of tracer nr. '//TRIM(int2str(itr))//' is not' 1749 CALL msg(TRIM(s)//' a boolean: '//TRIM(sval), modname, lerr) 1750 IF(.NOT.lerr) val = ival == 1 1751 END FUNCTION getKeyByIndex_lm11 1752 !============================================================================================================================== 1753 !============================================================================================================================== 1754 LOGICAL FUNCTION getKeyByIndex_s1m1(keyn, val, itr, ky, def, lDisp) RESULT(lerr) 1467 1755 CHARACTER(LEN=*), INTENT(IN) :: keyn 1468 1756 CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) :: val(:) 1469 CHARACTER(LEN=*), INTENT(IN) :: tname1757 INTEGER, INTENT(IN) :: itr 1470 1758 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1759 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: def 1760 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1761 !------------------------------------------------------------------------------------------------------------------------------ 1762 CHARACTER(LEN=maxlen) :: sval 1763 lerr = getKeyByIndex_sm11([keyn], sval, itr, ky, def, lDisp); IF(lerr) RETURN 1764 lerr = strParse(sval, ',', val) 1765 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 1766 END FUNCTION getKeyByIndex_s1m1 1767 !============================================================================================================================== 1768 LOGICAL FUNCTION getKeyByIndex_i1m1(keyn, val, itr, ky, def, lDisp) RESULT(lerr) 1769 CHARACTER(LEN=*), INTENT(IN) :: keyn 1770 INTEGER, ALLOCATABLE, INTENT(OUT) :: val(:) 1771 INTEGER, INTENT(IN) :: itr 1772 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1773 INTEGER, OPTIONAL, INTENT(IN) :: def 1774 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1775 !------------------------------------------------------------------------------------------------------------------------------ 1776 CHARACTER(LEN=maxlen) :: sval, s 1777 CHARACTER(LEN=maxlen), ALLOCATABLE :: svals(:) 1778 IF( PRESENT(def)) lerr = getKeyByIndex_sm11([keyn], sval, itr, ky, int2str(def), lDisp) 1779 IF(.NOT.PRESENT(def)) lerr = getKeyByIndex_sm11([keyn], sval, itr, ky, lDisp=lDisp) 1780 IF(lerr) RETURN 1781 lerr = strParse(sval, ',', svals) 1782 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 1783 val = str2int(svals) 1784 lerr = ANY(val == -HUGE(1)) 1785 s = 'key "'//TRIM(keyn)//'" of tracer nr. '//TRIM(int2str(itr))//' is not' 1786 CALL msg(TRIM(s)//' an integer: '//TRIM(sval), modname, lerr) 1787 END FUNCTION getKeyByIndex_i1m1 1788 !============================================================================================================================== 1789 LOGICAL FUNCTION getKeyByIndex_r1m1(keyn, val, itr, ky, def, lDisp) RESULT(lerr) 1790 CHARACTER(LEN=*), INTENT(IN) :: keyn 1791 REAL, ALLOCATABLE, INTENT(OUT) :: val(:) 1792 INTEGER, INTENT(IN) :: itr 1793 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1794 REAL, OPTIONAL, INTENT(IN) :: def 1795 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1796 !------------------------------------------------------------------------------------------------------------------------------ 1797 CHARACTER(LEN=maxlen) :: sval, s 1798 CHARACTER(LEN=maxlen), ALLOCATABLE :: svals(:) 1799 IF( PRESENT(def)) lerr = getKeyByIndex_sm11([keyn], sval, itr, ky, real2str(def), lDisp) 1800 IF(.NOT.PRESENT(def)) lerr = getKeyByIndex_sm11([keyn], sval, itr, ky, lDisp=lDisp) 1801 lerr = strParse(sval, ',', svals) 1802 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 1803 val = str2real(svals) 1804 lerr = ANY(val == -HUGE(1.)) 1805 s = 'key "'//TRIM(keyn)//'" of tracer nr. '//TRIM(int2str(itr))//' is not' 1806 CALL msg(TRIM(s)//' a real: '//TRIM(sval), modname, lerr) 1807 END FUNCTION getKeyByIndex_r1m1 1808 !============================================================================================================================== 1809 LOGICAL FUNCTION getKeyByIndex_l1m1(keyn, val, itr, ky, def, lDisp) RESULT(lerr) 1810 CHARACTER(LEN=*), INTENT(IN) :: keyn 1811 LOGICAL, ALLOCATABLE, INTENT(OUT) :: val(:) 1812 INTEGER, INTENT(IN) :: itr 1813 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1814 LOGICAL, OPTIONAL, INTENT(IN) :: def 1815 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1816 !------------------------------------------------------------------------------------------------------------------------------ 1817 CHARACTER(LEN=maxlen) :: sval, s 1818 CHARACTER(LEN=maxlen), ALLOCATABLE :: svals(:) 1819 INTEGER, ALLOCATABLE :: ivals(:) 1820 IF( PRESENT(def)) lerr = getKeyByIndex_sm11([keyn], sval, itr, ky, bool2str(def), lDisp) 1821 IF(.NOT.PRESENT(def)) lerr = getKeyByIndex_sm11([keyn], sval, itr, ky, lDisp=lDisp) 1822 lerr = strParse(sval, ',', svals) 1823 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 1824 ivals = str2bool(svals) 1825 lerr = ANY(ivals == -1) 1826 s = 'key "'//TRIM(keyn)//'" of tracer nr. '//TRIM(int2str(itr))//' is not' 1827 CALL msg(TRIM(s)//' a boolean: '//TRIM(sval), modname, lerr) 1828 IF(.NOT.lerr) val = ivals == 1 1829 END FUNCTION getKeyByIndex_l1m1 1830 !============================================================================================================================== 1831 !============================================================================================================================== 1832 LOGICAL FUNCTION getKeyByIndex_smm1(keyn, val, itr, ky, def, lDisp) RESULT(lerr) 1833 CHARACTER(LEN=*), INTENT(IN) :: keyn(:) 1834 CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) :: val(:) 1835 INTEGER, INTENT(IN) :: itr 1836 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1837 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: def 1838 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1471 1839 !------------------------------------------------------------------------------------------------------------------------------ 1472 1840 CHARACTER(LEN=maxlen) :: sval 1473 lerr = getKeyByName_s1(keyn, sval, tname, ky) 1474 IF(test(fmsg('missing key "'//TRIM(keyn)//'" for tracer "'//TRIM(tname)//'"', modname, lerr), lerr)) RETURN 1841 lerr = getKeyByIndex_sm11(keyn, sval, itr, ky, def, lDisp); IF(lerr) RETURN 1475 1842 lerr = strParse(sval, ',', val) 1476 END FUNCTION getKeyByName_s1m 1477 !============================================================================================================================== 1478 LOGICAL FUNCTION getKeyByName_sm(keyn, val, tname, ky, nam) RESULT(lerr) 1843 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 1844 END FUNCTION getKeyByIndex_smm1 1845 !============================================================================================================================== 1846 LOGICAL FUNCTION getKeyByIndex_imm1(keyn, val, itr, ky, def, lDisp) RESULT(lerr) 1847 CHARACTER(LEN=*), INTENT(IN) :: keyn(:) 1848 INTEGER, ALLOCATABLE, INTENT(OUT) :: val(:) 1849 INTEGER, INTENT(IN) :: itr 1850 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1851 INTEGER, OPTIONAL, INTENT(IN) :: def 1852 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1853 !------------------------------------------------------------------------------------------------------------------------------ 1854 CHARACTER(LEN=maxlen) :: sval, s 1855 CHARACTER(LEN=maxlen), ALLOCATABLE :: svals(:) 1856 IF( PRESENT(def)) lerr = getKeyByIndex_sm11(keyn, sval, itr, ky, int2str(def), lDisp) 1857 IF(.NOT.PRESENT(def)) lerr = getKeyByIndex_sm11(keyn, sval, itr, ky, lDisp=lDisp) 1858 IF(lerr) RETURN 1859 lerr = strParse(sval, ',', svals) 1860 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 1861 val = str2int(svals) 1862 lerr = ANY(val == -HUGE(1)) 1863 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of tracer nr. '//TRIM(int2str(itr))//' is not' 1864 CALL msg(TRIM(s)//' an integer: '//TRIM(sval), modname, lerr) 1865 END FUNCTION getKeyByIndex_imm1 1866 !============================================================================================================================== 1867 LOGICAL FUNCTION getKeyByIndex_rmm1(keyn, val, itr, ky, def, lDisp) RESULT(lerr) 1868 CHARACTER(LEN=*), INTENT(IN) :: keyn(:) 1869 REAL, ALLOCATABLE, INTENT(OUT) :: val(:) 1870 INTEGER, INTENT(IN) :: itr 1871 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1872 REAL, OPTIONAL, INTENT(IN) :: def 1873 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1874 !------------------------------------------------------------------------------------------------------------------------------ 1875 CHARACTER(LEN=maxlen) :: sval, s 1876 CHARACTER(LEN=maxlen), ALLOCATABLE :: svals(:) 1877 IF( PRESENT(def)) lerr = getKeyByIndex_sm11(keyn, sval, itr, ky, real2str(def), lDisp) 1878 IF(.NOT.PRESENT(def)) lerr = getKeyByIndex_sm11(keyn, sval, itr, ky, lDisp=lDisp) 1879 IF(lerr) RETURN 1880 lerr = strParse(sval, ',', svals) 1881 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 1882 val = str2real(svals) 1883 lerr = ANY(val == -HUGE(1.)) 1884 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of tracer nr. '//TRIM(int2str(itr))//' is not' 1885 CALL msg(TRIM(s)//' a real: '//TRIM(sval), modname, lerr) 1886 END FUNCTION getKeyByIndex_rmm1 1887 !============================================================================================================================== 1888 LOGICAL FUNCTION getKeyByIndex_lmm1(keyn, val, itr, ky, def, lDisp) RESULT(lerr) 1889 CHARACTER(LEN=*), INTENT(IN) :: keyn(:) 1890 LOGICAL, ALLOCATABLE, INTENT(OUT) :: val(:) 1891 INTEGER, INTENT(IN) :: itr 1892 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1893 LOGICAL, OPTIONAL, INTENT(IN) :: def 1894 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1895 !------------------------------------------------------------------------------------------------------------------------------ 1896 CHARACTER(LEN=maxlen) :: sval, s 1897 CHARACTER(LEN=maxlen), ALLOCATABLE :: svals(:) 1898 INTEGER, ALLOCATABLE :: ivals(:) 1899 IF( PRESENT(def)) lerr = getKeyByIndex_sm11(keyn, sval, itr, ky, bool2str(def), lDisp) 1900 IF(.NOT.PRESENT(def)) lerr = getKeyByIndex_sm11(keyn, sval, itr, ky, lDisp=lDisp) 1901 IF(lerr) RETURN 1902 lerr = strParse(sval, ',', svals) 1903 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 1904 ivals = str2bool(svals) 1905 lerr = ANY(ivals == -1) 1906 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of tracer nr. '//TRIM(int2str(itr))//' is not' 1907 CALL msg(TRIM(s)//' a boolean: '//TRIM(sval), modname, lerr) 1908 IF(.NOT.lerr) val = ivals == 1 1909 END FUNCTION getKeyByIndex_lmm1 1910 !============================================================================================================================== 1911 !============================================================================================================================== 1912 LOGICAL FUNCTION getKeyByIndex_s1mm(keyn, val, ky, nam, def, lDisp) RESULT(lerr) 1479 1913 CHARACTER(LEN=*), INTENT(IN) :: keyn 1480 1914 CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) :: val(:) 1481 CHARACTER(LEN=*), INTENT(IN) :: tname(:) 1482 TYPE(keys_type), OPTIONAL, TARGET, INTENT(IN) :: ky(:) 1915 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1483 1916 CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: nam(:) 1484 !------------------------------------------------------------------------------------------------------------------------------ 1485 TYPE(keys_type), POINTER :: keys(:) 1486 LOGICAL :: lk, lt, li 1487 INTEGER :: iq, nq 1488 1489 !--- DETERMINE THE DATABASE TO BE USED (ky, tracers or isotope) 1490 lk = PRESENT(ky) 1491 lt = .NOT.lk .AND. ALLOCATED(tracers); IF(lt) lt = SIZE(tracers) /= 0; IF(lt) lt = ANY(tracers(1)%keys%key(:) == keyn) 1492 li = .NOT.lt .AND. ALLOCATED(isotopes); IF(li) li = SIZE(isotopes) /= 0; IF(li) li = ANY(isotope%keys(1)%key(:) == keyn) 1493 1494 !--- LINK "keys" TO THE RIGHT DATABASE 1495 IF(test(.NOT.ANY([lk,lt,li]), lerr)) RETURN 1496 IF(lk) keys => ky(:) 1497 IF(lt) keys => tracers(:)%keys 1498 IF(li) keys => isotope%keys(:) 1499 1500 !--- GET THE DATA 1501 nq = SIZE(tname) 1502 ALLOCATE(val(nq)) 1503 lerr = ANY([(getKeyByName_s1(keyn, val(iq), tname(iq), keys(:)), iq=1, nq)]) 1504 IF(PRESENT(nam)) nam = tname(:) 1505 1506 END FUNCTION getKeyByName_sm 1507 !============================================================================================================================== 1508 LOGICAL FUNCTION getKey_sm(keyn, val, ky, nam) RESULT(lerr) 1917 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: def 1918 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1919 lerr = getKeyByIndex_smmm([keyn], val, ky, nam, def, lDisp) 1920 END FUNCTION getKeyByIndex_s1mm 1921 !============================================================================================================================== 1922 LOGICAL FUNCTION getKeyByIndex_i1mm(keyn, val, ky, nam, def, lDisp) RESULT(lerr) 1509 1923 CHARACTER(LEN=*), INTENT(IN) :: keyn 1510 CHARACTER(LEN=maxlen),ALLOCATABLE, INTENT(OUT) :: val(:)1511 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:)1924 INTEGER, ALLOCATABLE, INTENT(OUT) :: val(:) 1925 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1512 1926 CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: nam(:) 1513 !------------------------------------------------------------------------------------------------------------------------------ 1514 ! Note: if names are repeated, getKeyByName_sm can't be used ; this routine, using indexes, must be used instead. 1515 IF(PRESENT(ky)) THEN !=== KEY FROM "ky" 1516 val = fgetKeys(keyn, ky, lerr=lerr) 1517 IF(PRESENT(nam)) nam = ky(:)%name 1518 ELSE 1519 IF( .NOT.test(.NOT.ALLOCATED(tracers ), lerr)) lerr = SIZE(tracers ) == 0 !=== KEY FROM "tracers" 1520 IF(.NOT.lerr) val = fgetKeys(keyn, tracers%keys, lerr=lerr) 1521 IF(.NOT.lerr.AND.PRESENT(nam)) nam = tracers(:)%keys%name 1522 IF(lerr.AND..NOT.test(.NOT.ALLOCATED(isotopes), lerr)) lerr = SIZE(isotopes) == 0 !=== KEY FROM "isotope" 1523 IF(.NOT.lerr) val = fgetKeys(keyn, isotope%keys, lerr=lerr) 1524 IF(.NOT.lerr.AND.PRESENT(nam)) nam = isotope%keys(:)%name 1927 INTEGER, OPTIONAL, INTENT(IN) :: def 1928 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 1929 lerr = getKeyByIndex_immm([keyn], val, ky, nam, def, lDisp) 1930 END FUNCTION getKeyByIndex_i1mm 1931 !============================================================================================================================== 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) 1940 END FUNCTION getKeyByIndex_r1mm 1941 !============================================================================================================================== 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) 1950 END FUNCTION getKeyByIndex_l1mm 1951 !============================================================================================================================== 1952 !============================================================================================================================== 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 1960 !------------------------------------------------------------------------------------------------------------------------------ 1961 CHARACTER(LEN=maxlen) :: s 1962 CHARACTER(LEN=maxlen), ALLOCATABLE :: tname(:) 1963 INTEGER :: iq, nq(3), k 1964 LOGICAL :: lD, l(3) 1965 lD = .TRUE.; IF(PRESENT(lDisp)) lD = lDisp 1966 s = 'key "'//TRIM(strStack(keyn, '/'))//'"' 1967 lerr = .TRUE. 1968 IF(PRESENT(ky)) THEN; val = fgetKey(ky) !--- "ky" 1969 ELSE IF(ALLOCATED(tracers)) THEN; val = fgetKey(tracers(:)%keys) !--- "tracers" 1970 IF(lerr .AND. ASSOCIATED(isotope)) val = fgetKey(isotope%keys(:)) !--- "isotope" 1525 1971 END IF 1526 END FUNCTION getKey_sm 1527 !============================================================================================================================== 1528 LOGICAL FUNCTION getKeyByName_i1(keyn, val, tname, ky) RESULT(lerr) 1529 CHARACTER(LEN=*), INTENT(IN) :: keyn 1530 INTEGER, INTENT(OUT) :: val 1531 CHARACTER(LEN=*), INTENT(IN) :: tname 1532 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1533 !------------------------------------------------------------------------------------------------------------------------------ 1534 CHARACTER(LEN=maxlen) :: sval 1535 INTEGER :: ierr 1536 lerr = getKeyByName_s1(keyn, sval, tname, ky) 1537 IF(test(fmsg('key "'//TRIM(keyn)//'" or tracer "'//TRIM(tname)//'" is missing', modname, lerr), lerr)) RETURN 1538 READ(sval, *, IOSTAT=ierr) val 1539 IF(test(fmsg('key "'//TRIM(keyn)//'" of tracer "'//TRIM(tname)//'" is not an integer', modname, ierr/=0), lerr)) RETURN 1540 END FUNCTION getKeyByName_i1 1541 !============================================================================================================================== 1542 LOGICAL FUNCTION getKeyByName_i1m(keyn, val, tname, ky) RESULT(lerr) 1543 CHARACTER(LEN=*), INTENT(IN) :: keyn 1544 INTEGER, ALLOCATABLE, INTENT(OUT) :: val(:) 1545 CHARACTER(LEN=*), INTENT(IN) :: tname 1546 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1547 !------------------------------------------------------------------------------------------------------------------------------ 1548 CHARACTER(LEN=maxlen), ALLOCATABLE :: sval(:) 1549 INTEGER :: ierr, iq, nq 1550 IF(test(getKeyByName_s1m(keyn, sval, tname, ky), lerr)) RETURN 1551 nq = SIZE(sval); ALLOCATE(val(nq)) 1552 lerr = .FALSE.; DO iq=1, nq; READ(sval(iq), *, IOSTAT=ierr) val(iq); lerr = lerr .OR. ierr /= 0; END DO 1553 IF(test(fmsg('key "'//TRIM(keyn)//'" of tracer "'//TRIM(tname)//'" is not an integer', modname, lerr), lerr)) RETURN 1554 END FUNCTION getKeyByName_i1m 1555 !============================================================================================================================== 1556 LOGICAL FUNCTION getKeyByName_im(keyn, val, tname, ky, nam) RESULT(lerr) 1557 CHARACTER(LEN=*), INTENT(IN) :: keyn 1558 INTEGER, ALLOCATABLE, INTENT(OUT) :: val(:) 1559 CHARACTER(LEN=*), INTENT(IN) :: tname(:) 1560 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1561 CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: nam(:) 1562 !------------------------------------------------------------------------------------------------------------------------------ 1563 CHARACTER(LEN=maxlen), ALLOCATABLE :: sval(:), names(:) 1564 INTEGER :: ierr, iq, nq 1565 IF(test(getKeyByName_sm(keyn, sval, tname, ky, names), lerr)) RETURN 1566 nq = SIZE(sval); ALLOCATE(val(nq)) 1567 DO iq = 1, nq !--- CONVERT THE KEYS TO INTEGERS 1568 READ(sval(iq), *, IOSTAT=ierr) val(iq) 1569 IF(test(fmsg('key "'//TRIM(keyn)//'" of tracer "'//TRIM(names(iq))//'" is not an integer', modname, ierr/=0), lerr)) RETURN 1570 END DO 1571 IF(PRESENT(nam)) nam = names(:) 1572 END FUNCTION getKeyByName_im 1573 !============================================================================================================================== 1574 LOGICAL FUNCTION getKey_im(keyn, val, ky, nam) RESULT(lerr) 1575 CHARACTER(LEN=*), INTENT(IN) :: keyn 1972 IF(.NOT.lerr) THEN; IF(PRESENT(nam)) nam = tname; RETURN; END IF 1973 IF(.NOT.PRESENT(def)) THEN; CALL msg('No '//TRIM(s)//' found', modname, lD); RETURN; END IF 1974 1975 !--- DEFAULT VALUE 1976 l = [PRESENT(ky), ALLOCATED(tracers), ASSOCIATED(isotope)]; nq(:) = 0 1977 IF(l(1)) nq(1) = SIZE(ky) 1978 IF(l(2)) nq(2) = SIZE(tracers) 1979 IF(l(3)) nq(3) = SIZE(isotope%keys) 1980 DO k = 1, 3; IF(l(k) .AND. nq(k) /= 0) THEN; val = [(def, iq = 1, nq(k))]; EXIT; END IF; END DO 1981 lerr = k == 4 1982 CALL msg('Using defaut value for '//TRIM(s)//': '//TRIM(def), modname, lD .AND. .NOT.lerr) 1983 CALL msg('No '//TRIM(s), modname, lD .AND. lerr) 1984 1985 CONTAINS 1986 1987 FUNCTION fgetKey(ky) RESULT(val) 1988 CHARACTER(LEN=maxlen), ALLOCATABLE :: val(:) 1989 TYPE(keys_type), INTENT(IN) :: ky(:) 1990 LOGICAL :: ler(SIZE(ky)) 1991 INTEGER :: iq 1992 lerr = SIZE(ky) == 0; IF(lerr) RETURN 1993 tname = ky%name 1994 val = [(fgetKeyIdx(iq, keyn(:), ky, ler(iq)), iq = 1, SIZE(ky))] 1995 lerr = ANY(ler) 1996 END FUNCTION fgetKey 1997 1998 END FUNCTION getKeyByIndex_smmm 1999 !============================================================================================================================== 2000 LOGICAL FUNCTION getKeyByIndex_immm(keyn, val, ky, nam, def, lDisp) RESULT(lerr) 2001 CHARACTER(LEN=*), INTENT(IN) :: keyn(:) 1576 2002 INTEGER, ALLOCATABLE, INTENT(OUT) :: val(:) 1577 2003 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1578 2004 CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: nam(:) 1579 !------------------------------------------------------------------------------------------------------------------------------ 1580 CHARACTER(LEN=maxlen), ALLOCATABLE :: sval(:), names(:) 1581 INTEGER :: ierr, iq, nq 1582 IF(test(getKey_sm(keyn, sval, ky, names), lerr)) RETURN 1583 nq = SIZE(sval); ALLOCATE(val(nq)) 1584 DO iq = 1, nq 1585 READ(sval(iq), *, IOSTAT=ierr) val(iq) 1586 IF(test(fmsg('key "'//TRIM(keyn)//'" of tracer "'//TRIM(names(iq))//'" is not an integer', modname, ierr/=0), lerr)) RETURN 1587 END DO 1588 IF(PRESENT(nam)) nam = names 1589 END FUNCTION getKey_im 1590 !============================================================================================================================== 1591 LOGICAL FUNCTION getKeyByName_r1(keyn, val, tname, ky) RESULT(lerr) 1592 CHARACTER(LEN=*), INTENT(IN) :: keyn 1593 REAL, INTENT(OUT) :: val 1594 CHARACTER(LEN=*), INTENT(IN) :: tname 1595 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1596 !------------------------------------------------------------------------------------------------------------------------------ 1597 CHARACTER(LEN=maxlen) :: sval 1598 INTEGER :: ierr 1599 lerr = getKeyByName_s1(keyn, sval, tname, ky) 1600 IF(test(fmsg('key "'//TRIM(keyn)//'" or tracer "'//TRIM(tname)//'" is missing', modname, lerr), lerr)) RETURN 1601 READ(sval, *, IOSTAT=ierr) val 1602 IF(test(fmsg('key "'//TRIM(keyn)//'" of tracer "'//TRIM(tname)//'" is not a real', modname, ierr/=0), lerr)) RETURN 1603 END FUNCTION getKeyByName_r1 1604 !============================================================================================================================== 1605 LOGICAL FUNCTION getKeyByName_r1m(keyn, val, tname, ky) RESULT(lerr) 1606 CHARACTER(LEN=*), INTENT(IN) :: keyn 1607 REAL, ALLOCATABLE, INTENT(OUT) :: val(:) 1608 CHARACTER(LEN=*), INTENT(IN) :: tname 1609 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1610 !------------------------------------------------------------------------------------------------------------------------------ 1611 CHARACTER(LEN=maxlen), ALLOCATABLE :: sval(:) 1612 INTEGER :: ierr, iq, nq 1613 IF(test(getKeyByName_s1m(keyn, sval, tname, ky), lerr)) RETURN 1614 nq = SIZE(sval); ALLOCATE(val(nq)) 1615 lerr = .FALSE.; DO iq=1, nq; READ(sval(iq), *, IOSTAT=ierr) val(iq); lerr = lerr .OR. ierr /= 0; END DO 1616 IF(test(fmsg('key "'//TRIM(keyn)//'" of tracer "'//TRIM(tname)//'" is not a vector of reals', modname, lerr), lerr)) RETURN 1617 END FUNCTION getKeyByName_r1m 1618 !============================================================================================================================== 1619 LOGICAL FUNCTION getKeyByName_rm(keyn, val, tname, ky, nam) RESULT(lerr) 1620 CHARACTER(LEN=*), INTENT(IN) :: keyn 1621 REAL, ALLOCATABLE, INTENT(OUT) :: val(:) 1622 CHARACTER(LEN=*), INTENT(IN) :: tname(:) 1623 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1624 CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: nam(:) 1625 !------------------------------------------------------------------------------------------------------------------------------ 1626 CHARACTER(LEN=maxlen), ALLOCATABLE :: sval(:), names(:) 1627 INTEGER :: ierr, iq, nq 1628 IF(test(getKeyByName_sm(keyn, sval, tname, ky, names), lerr)) RETURN 1629 nq = SIZE(sval); ALLOCATE(val(nq)) 1630 DO iq = 1, nq !--- CONVERT THE KEYS TO INTEGERS 1631 READ(sval(iq), *, IOSTAT=ierr) val(iq) 1632 IF(test(fmsg('key "'//TRIM(keyn)//'" of tracer "'//TRIM(names(iq))//'" is not a real', modname, ierr/=0), lerr)) RETURN 1633 END DO 1634 IF(PRESENT(nam)) nam = names 1635 END FUNCTION getKeyByName_rm 1636 !============================================================================================================================== 1637 LOGICAL FUNCTION getKey_rm(keyn, val, ky, nam) RESULT(lerr) 1638 CHARACTER(LEN=*), INTENT(IN) :: keyn 2005 INTEGER, OPTIONAL, INTENT(IN) :: def 2006 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2007 !------------------------------------------------------------------------------------------------------------------------------ 2008 CHARACTER(LEN=maxlen) :: s 2009 CHARACTER(LEN=maxlen), ALLOCATABLE :: svals(:), tname(:) 2010 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) 2013 IF(lerr) RETURN 2014 val = str2int(svals) 2015 ll = val == -HUGE(1) 2016 lerr = ANY(ll); IF(.NOT.lerr) THEN; IF(PRESENT(nam)) nam = tname; RETURN; END IF 2017 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(strStack(PACK(tname, MASK=ll)))//' is not' 2018 CALL msg(TRIM(s)//' an integer: '//TRIM(strStack(svals, MASK=ll)), modname, lerr) 2019 IF(.NOT.lerr .AND. PRESENT(nam)) nam = tname 2020 END FUNCTION getKeyByIndex_immm 2021 !============================================================================================================================== 2022 LOGICAL FUNCTION getKeyByIndex_rmmm(keyn, val, ky, nam, def, lDisp) RESULT(lerr) 2023 CHARACTER(LEN=*), INTENT(IN) :: keyn(:) 1639 2024 REAL, ALLOCATABLE, INTENT(OUT) :: val(:) 1640 2025 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1641 2026 CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: nam(:) 1642 !------------------------------------------------------------------------------------------------------------------------------ 1643 CHARACTER(LEN=maxlen), ALLOCATABLE :: sval(:), names(:) 1644 INTEGER :: ierr, iq, nq 1645 IF(test(getKey_sm(keyn, sval, ky, names), lerr)) RETURN 1646 nq = SIZE(sval); ALLOCATE(val(nq)) 1647 DO iq = 1, nq !--- CONVERT THE KEYS TO INTEGERS 1648 READ(sval(iq), *, IOSTAT=ierr) val(iq) 1649 IF(test(fmsg('key "'//TRIM(keyn)//'" of tracer "'//TRIM(names(iq))//'" is not a real', modname, ierr/=0), lerr)) RETURN 1650 END DO 1651 IF(PRESENT(nam)) nam = names 1652 END FUNCTION getKey_rm 1653 !============================================================================================================================== 1654 LOGICAL FUNCTION getKeyByName_l1(keyn, val, tname, ky) RESULT(lerr) 1655 USE strings_mod, ONLY: str2bool 1656 CHARACTER(LEN=*), INTENT(IN) :: keyn 1657 LOGICAL, INTENT(OUT) :: val 1658 CHARACTER(LEN=*), INTENT(IN) :: tname 1659 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1660 !------------------------------------------------------------------------------------------------------------------------------ 1661 CHARACTER(LEN=maxlen) :: sval 1662 lerr = getKeyByName_s1(keyn, sval, tname, ky) 1663 IF(test(fmsg('key "'//TRIM(keyn)//'" or tracer "'//TRIM(tname)//'" is missing', modname, lerr), lerr)) RETURN 1664 val = str2bool(sval) 1665 END FUNCTION getKeyByName_l1 1666 !============================================================================================================================== 1667 LOGICAL FUNCTION getKeyByName_l1m(keyn, val, tname, ky) RESULT(lerr) 1668 USE strings_mod, ONLY: str2bool 1669 CHARACTER(LEN=*), INTENT(IN) :: keyn 1670 LOGICAL, ALLOCATABLE, INTENT(OUT) :: val(:) 1671 CHARACTER(LEN=*), INTENT(IN) :: tname 1672 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1673 !------------------------------------------------------------------------------------------------------------------------------ 1674 CHARACTER(LEN=maxlen), ALLOCATABLE :: sval(:) 1675 INTEGER :: iq, nq 1676 IF(test(getKeyByName_s1m(keyn, sval, tname, ky), lerr)) RETURN 1677 nq = SIZE(sval); ALLOCATE(val(nq)) 1678 lerr = .FALSE.; DO iq=1, nq; val(iq)=str2bool(sval(iq)); END DO 1679 END FUNCTION getKeyByName_l1m 1680 !============================================================================================================================== 1681 LOGICAL FUNCTION getKeyByName_lm(keyn, val, tname, ky, nam) RESULT(lerr) 1682 USE strings_mod, ONLY: str2bool 1683 CHARACTER(LEN=*), INTENT(IN) :: keyn 1684 LOGICAL, ALLOCATABLE, INTENT(OUT) :: val(:) 1685 CHARACTER(LEN=*), INTENT(IN) :: tname(:) 1686 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1687 CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: nam(:) 1688 !------------------------------------------------------------------------------------------------------------------------------ 1689 CHARACTER(LEN=maxlen), ALLOCATABLE :: sval(:) 1690 INTEGER :: iq, nq 1691 IF(test(getKeyByName_sm(keyn, sval, tname, ky, nam), lerr)) RETURN 1692 nq = SIZE(sval); ALLOCATE(val(nq)) 1693 lerr = .FALSE.; DO iq=1, nq; val(iq)=str2bool(sval(iq)); END DO 1694 END FUNCTION getKeyByName_lm 1695 !============================================================================================================================== 1696 LOGICAL FUNCTION getKey_lm(keyn, val, ky, nam) RESULT(lerr) 1697 USE strings_mod, ONLY: str2bool 1698 CHARACTER(LEN=*), INTENT(IN) :: keyn 2027 REAL, OPTIONAL, INTENT(IN) :: def 2028 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2029 !------------------------------------------------------------------------------------------------------------------------------ 2030 CHARACTER(LEN=maxlen) :: s 2031 CHARACTER(LEN=maxlen), ALLOCATABLE :: svals(:), tname(:) 2032 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) 2035 IF(lerr) RETURN 2036 val = str2real(svals) 2037 ll = val == -HUGE(1.) 2038 lerr = ANY(ll); IF(.NOT.lerr) THEN; IF(PRESENT(nam)) nam = tname; RETURN; END IF 2039 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(strStack(PACK(tname, MASK=ll)))//' is not a' 2040 CALL msg(TRIM(s)//' a real: '//TRIM(strStack(svals, MASK=ll)), modname) 2041 END FUNCTION getKeyByIndex_rmmm 2042 !============================================================================================================================== 2043 LOGICAL FUNCTION getKeyByIndex_lmmm(keyn, val, ky, nam, def, lDisp) RESULT(lerr) 2044 CHARACTER(LEN=*), INTENT(IN) :: keyn(:) 1699 2045 LOGICAL, ALLOCATABLE, INTENT(OUT) :: val(:) 1700 2046 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1701 2047 CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: nam(:) 1702 !------------------------------------------------------------------------------------------------------------------------------ 1703 CHARACTER(LEN=maxlen), ALLOCATABLE :: sval(:) 2048 LOGICAL, OPTIONAL, INTENT(IN) :: def 2049 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2050 !------------------------------------------------------------------------------------------------------------------------------ 2051 CHARACTER(LEN=maxlen) :: s 2052 CHARACTER(LEN=maxlen), ALLOCATABLE :: svals(:), tname(:) 2053 LOGICAL, ALLOCATABLE :: ll(:) 2054 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) 2057 IF(lerr) RETURN 2058 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 2061 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(strStack(tname, MASK=ll))//' is not' 2062 CALL msg(TRIM(s)//' a boolean: '//TRIM(strStack(svals, MASK=ll)), modname) 2063 END FUNCTION getKeyByIndex_lmmm 2064 !============================================================================================================================== 2065 2066 2067 2068 !============================================================================================================================== 2069 !=== GET KEYS VALUES FROM TRACERS NAMES === 2070 !============================================================================================================================== 2071 !=== TRY TO GET THE KEY NAMED "key" FOR THE TRACER NAMED "tname" IN: === 2072 !=== * ARGUMENT "ky" DATABASE IF SPECIFIED ; OTHERWISE: === 2073 !=== * IN INTERNAL TRACERS DATABASE "tracers(:)%keys" (IF UNFOUND, IN INTERNAL ISOTOPES DATABASE "isotope%keys(:)") === 2074 !=== THE RETURNED VALUE (STRING, AN INTEGER, A REAL OR A LOGICAL) CAN BE EITHER: === 2075 !=== * A SCALAR === 2076 !=== * A VECTOR, WHICH IS THE FOUND VALUE PARSED WITH THE SEPARATOR "," === 2077 !=== === 2078 !=== SYNTAX: lerr = getKeyByName_{sirl}{1m}{1m}1(keyn[(:)], val[(:)], tname [, ky(:)][, def][, lDisp]) === 2079 !============================================================================================================================== 2080 !=== IF "tname(:)" IS A VECTOR, THE RETURNED VALUES (ONE EACH "tname(:)" ELEMENT) ARE STORED IN THE VECTOR "val(:)" === 2081 !=== === 2082 !=== SYNTAX lerr = getKeyByName_{sirl}{1m}mm (keyn[(:)], val (:), tname(:)[, ky(:)][, def][, lDisp]) === 2083 !============================================================================================================================== 2084 LOGICAL FUNCTION getKeyByName_s111(keyn, val, tname, ky, def, lDisp) RESULT(lerr) 2085 CHARACTER(LEN=*), INTENT(IN) :: keyn, tname 2086 CHARACTER(LEN=maxlen), INTENT(OUT) :: val 2087 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2088 CHARACTER(LEN=*),OPTIONAL, INTENT(IN) :: def 2089 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2090 lerr = getKeyByName_sm11([keyn], val, tname, ky, def, lDisp) 2091 END FUNCTION getKeyByName_s111 2092 !============================================================================================================================== 2093 LOGICAL FUNCTION getKeyByName_i111(keyn, val, tname, ky, def, lDisp) RESULT(lerr) 2094 CHARACTER(LEN=*), INTENT(IN) :: keyn, tname 2095 INTEGER, INTENT(OUT) :: val 2096 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2097 INTEGER, OPTIONAL, INTENT(IN) :: def 2098 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2099 lerr = getKeyByName_im11([keyn], val, tname, ky, def, lDisp) 2100 END FUNCTION getKeyByName_i111 2101 !============================================================================================================================== 2102 LOGICAL FUNCTION getKeyByName_r111(keyn, val, tname, ky, def, lDisp) RESULT(lerr) 2103 CHARACTER(LEN=*), INTENT(IN) :: keyn, tname 2104 REAL , INTENT(OUT) :: val 2105 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2106 REAL, OPTIONAL, INTENT(IN) :: def 2107 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2108 lerr = getKeyByName_rm11([keyn], val, tname, ky, def, lDisp) 2109 END FUNCTION getKeyByName_r111 2110 !============================================================================================================================== 2111 LOGICAL FUNCTION getKeyByName_l111(keyn, val, tname, ky, def, lDisp) RESULT(lerr) 2112 CHARACTER(LEN=*), INTENT(IN) :: keyn, tname 2113 LOGICAL, INTENT(OUT) :: val 2114 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2115 LOGICAL, OPTIONAL, INTENT(IN) :: def 2116 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2117 lerr = getKeyByName_lm11([keyn], val, tname, ky, def, lDisp) 2118 END FUNCTION getKeyByName_l111 2119 !============================================================================================================================== 2120 !============================================================================================================================== 2121 LOGICAL FUNCTION getKeyByName_sm11(keyn, val, tname, ky, def, lDisp) RESULT(lerr) 2122 CHARACTER(LEN=*), INTENT(IN) :: keyn(:), tname 2123 CHARACTER(LEN=maxlen), INTENT(OUT) :: val 2124 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2125 CHARACTER(LEN=*),OPTIONAL, INTENT(IN) :: def 2126 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2127 !------------------------------------------------------------------------------------------------------------------------------ 2128 CHARACTER(LEN=maxlen) :: s, tnam 2129 LOGICAL :: lD 2130 lD = .TRUE.; IF(PRESENT(lDisp)) lD = lDisp 2131 s = 'key "'//TRIM(strStack(keyn, '/'))//'" for "'//TRIM(tname)//'"' 2132 lerr = .TRUE. 2133 tnam = strHead(delPhase(tname),'_',.TRUE.) !--- Remove phase and tag 2134 IF(lerr .AND. PRESENT(ky)) val = fgetKey(ky) !--- "ky" 2135 IF(lerr .AND. ALLOCATED (tracers)) val = fgetKey(tracers(:)%keys) !--- "tracers" 2136 IF(lerr .AND. ASSOCIATED(isotope)) val = fgetKey(isotope%keys(:)) !--- "isotope" 2137 IF(lerr .AND. PRESENT(def)) THEN 2138 val = def; lerr = .NOT.PRESENT(def) 2139 CALL msg('Using defaut value of '//TRIM(s)//': '//TRIM(def), modname, lD) 2140 END IF 2141 CALL msg('No '//TRIM(s)//' or out of bounds index', modname, lD .AND. lerr) 2142 2143 CONTAINS 2144 2145 CHARACTER(LEN=maxlen) FUNCTION fgetKey(ky) RESULT(val) 2146 TYPE(keys_type), INTENT(IN) :: ky(:) 2147 lerr = SIZE(ky) == 0 2148 IF(lerr) RETURN 2149 val = fgetKeyIdx(strIdx(ky%name, tname), [keyn], ky, lerr) 2150 IF(lerr) val = fgetKeyIdx(strIdx(ky%name, tnam ), [keyn], ky, lerr) 2151 2152 END FUNCTION fgetKey 2153 2154 END FUNCTION getKeyByName_sm11 2155 !============================================================================================================================== 2156 LOGICAL FUNCTION getKeyByName_im11(keyn, val, tname, ky, def, lDisp) RESULT(lerr) 2157 CHARACTER(LEN=*), INTENT(IN) :: keyn(:), tname 2158 INTEGER, INTENT(OUT) :: val 2159 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2160 INTEGER, OPTIONAL, INTENT(IN) :: def 2161 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2162 !------------------------------------------------------------------------------------------------------------------------------ 2163 CHARACTER(LEN=maxlen) :: sval, s 2164 IF( PRESENT(def)) lerr = getKeyByName_sm11(keyn, sval, tname, ky, int2str(def), lDisp) 2165 IF(.NOT.PRESENT(def)) lerr = getKeyByName_sm11(keyn, sval, tname, ky, lDisp=lDisp) 2166 IF(lerr) RETURN 2167 val = str2int(sval) 2168 lerr = val == -HUGE(1) 2169 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(tname)//' is not' 2170 CALL msg(TRIM(s)//' an integer: '//TRIM(sval), modname, lerr) 2171 END FUNCTION getKeyByName_im11 2172 !============================================================================================================================== 2173 LOGICAL FUNCTION getKeyByName_rm11(keyn, val, tname, ky, def, lDisp) RESULT(lerr) 2174 CHARACTER(LEN=*), INTENT(IN) :: keyn(:), tname 2175 REAL , INTENT(OUT) :: val 2176 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2177 REAL, OPTIONAL, INTENT(IN) :: def 2178 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2179 !------------------------------------------------------------------------------------------------------------------------------ 2180 CHARACTER(LEN=maxlen) :: sval, s 2181 IF( PRESENT(def)) lerr = getKeyByName_sm11(keyn, sval, tname, ky, real2str(def), lDisp) 2182 IF(.NOT.PRESENT(def)) lerr = getKeyByName_sm11(keyn, sval, tname, ky, lDisp=lDisp) 2183 IF(lerr) RETURN 2184 val = str2real(sval) 2185 lerr = val == -HUGE(1.) 2186 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(tname)//' is not' 2187 CALL msg(TRIM(s)//' a real: '//TRIM(sval), modname, lerr) 2188 END FUNCTION getKeyByName_rm11 2189 !============================================================================================================================== 2190 LOGICAL FUNCTION getKeyByName_lm11(keyn, val, tname, ky, def, lDisp) RESULT(lerr) 2191 CHARACTER(LEN=*), INTENT(IN) :: keyn(:), tname 2192 LOGICAL, INTENT(OUT) :: val 2193 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2194 LOGICAL, OPTIONAL, INTENT(IN) :: def 2195 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2196 !------------------------------------------------------------------------------------------------------------------------------ 2197 CHARACTER(LEN=maxlen) :: sval, s 2198 INTEGER :: ival 2199 IF( PRESENT(def)) lerr = getKeyByName_sm11(keyn, sval, tname, ky, bool2str(def), lDisp) 2200 IF(.NOT.PRESENT(def)) lerr = getKeyByName_sm11(keyn, sval, tname, ky, lDisp=lDisp) 2201 IF(lerr) RETURN 2202 ival = str2bool(sval) 2203 lerr = ival == -1 2204 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(tname)//' is not' 2205 CALL msg(TRIM(s)//' a boolean: '//TRIM(sval), modname, lerr) 2206 IF(.NOT.lerr) val = ival == 1 2207 END FUNCTION getKeyByName_lm11 2208 !============================================================================================================================== 2209 !============================================================================================================================== 2210 LOGICAL FUNCTION getKeyByName_s1m1(keyn, val, tname, ky, def, lDisp) RESULT(lerr) 2211 CHARACTER(LEN=*), INTENT(IN) :: keyn, tname 2212 CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) :: val(:) 2213 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2214 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: def 2215 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2216 !------------------------------------------------------------------------------------------------------------------------------ 2217 CHARACTER(LEN=maxlen) :: sval 2218 lerr = getKeyByName_sm11([keyn], sval, tname, ky, def, lDisp); IF(lerr) RETURN 2219 lerr = strParse(sval, ',', val) 2220 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 2221 END FUNCTION getKeyByName_s1m1 2222 !============================================================================================================================== 2223 LOGICAL FUNCTION getKeyByName_i1m1(keyn, val, tname, ky, def, lDisp) RESULT(lerr) 2224 CHARACTER(LEN=*), INTENT(IN) :: keyn, tname 2225 INTEGER, ALLOCATABLE, INTENT(OUT) :: val(:) 2226 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2227 INTEGER, OPTIONAL, INTENT(IN) :: def 2228 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2229 !------------------------------------------------------------------------------------------------------------------------------ 2230 CHARACTER(LEN=maxlen) :: sval, s 2231 CHARACTER(LEN=maxlen), ALLOCATABLE :: svals(:) 2232 IF( PRESENT(def)) lerr = getKeyByName_sm11([keyn], sval, tname, ky, int2str(def), lDisp) 2233 IF(.NOT.PRESENT(def)) lerr = getKeyByName_sm11([keyn], sval, tname, ky, lDisp=lDisp) 2234 IF(lerr) RETURN 2235 lerr = strParse(sval, ',', svals) 2236 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 2237 val = str2int(svals) 2238 lerr = ANY(val == -HUGE(1)) 2239 s = 'key "'//TRIM(keyn)//'" of '//TRIM(tname)//' is not' 2240 CALL msg(TRIM(s)//' an integer: '//TRIM(sval), modname, lerr) 2241 END FUNCTION getKeyByName_i1m1 2242 !============================================================================================================================== 2243 LOGICAL FUNCTION getKeyByName_r1m1(keyn, val, tname, ky, def, lDisp) RESULT(lerr) 2244 CHARACTER(LEN=*), INTENT(IN) :: keyn, tname 2245 REAL, ALLOCATABLE, INTENT(OUT) :: val(:) 2246 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2247 REAL, OPTIONAL, INTENT(IN) :: def 2248 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2249 !------------------------------------------------------------------------------------------------------------------------------ 2250 CHARACTER(LEN=maxlen) :: sval, s 2251 CHARACTER(LEN=maxlen), ALLOCATABLE :: svals(:) 2252 IF( PRESENT(def)) lerr = getKeyByName_sm11([keyn], sval, tname, ky, real2str(def), lDisp) 2253 IF(.NOT.PRESENT(def)) lerr = getKeyByName_sm11([keyn], sval, tname, ky, lDisp=lDisp) 2254 IF(lerr) RETURN 2255 lerr = strParse(sval, ',', svals) 2256 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 2257 val = str2real(svals) 2258 lerr = ANY(val == -HUGE(1.)) 2259 s = 'key "'//TRIM(keyn)//'" of '//TRIM(tname)//' is not' 2260 CALL msg(TRIM(s)//' a real: '//TRIM(sval), modname, lerr) 2261 END FUNCTION getKeyByName_r1m1 2262 !============================================================================================================================== 2263 LOGICAL FUNCTION getKeyByName_l1m1(keyn, val, tname, ky, def, lDisp) RESULT(lerr) 2264 CHARACTER(LEN=*), INTENT(IN) :: keyn, tname 2265 LOGICAL, ALLOCATABLE, INTENT(OUT) :: val(:) 2266 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2267 LOGICAL, OPTIONAL, INTENT(IN) :: def 2268 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2269 !------------------------------------------------------------------------------------------------------------------------------ 2270 CHARACTER(LEN=maxlen) :: sval, s 2271 CHARACTER(LEN=maxlen), ALLOCATABLE :: svals(:) 2272 INTEGER, ALLOCATABLE :: ivals(:) 2273 IF( PRESENT(def)) lerr = getKeyByName_sm11([keyn], sval, tname, ky, bool2str(def), lDisp) 2274 IF(.NOT.PRESENT(def)) lerr = getKeyByName_sm11([keyn], sval, tname, ky, lDisp=lDisp) 2275 IF(lerr) RETURN 2276 lerr = strParse(sval, ',', svals) 2277 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 2278 ivals = str2bool(svals) 2279 lerr = ANY(ivals == -1) 2280 s = 'key "'//TRIM(keyn)//'" of '//TRIM(tname)//' is not' 2281 CALL msg(TRIM(s)//' a boolean: '//TRIM(sval), modname, lerr) 2282 IF(.NOT.lerr) val = ivals == 1 2283 END FUNCTION getKeyByName_l1m1 2284 !============================================================================================================================== 2285 !============================================================================================================================== 2286 LOGICAL FUNCTION getKeyByName_smm1(keyn, val, tname, ky, def, lDisp) RESULT(lerr) 2287 CHARACTER(LEN=*), INTENT(IN) :: keyn(:), tname 2288 CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) :: val(:) 2289 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2290 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: def 2291 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2292 !------------------------------------------------------------------------------------------------------------------------------ 2293 CHARACTER(LEN=maxlen) :: sval 2294 lerr = getKeyByName_sm11(keyn, sval, tname, ky, def, lDisp); IF(lerr) RETURN 2295 lerr = strParse(sval, ',', val) 2296 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 2297 END FUNCTION getKeyByName_smm1 2298 !============================================================================================================================== 2299 LOGICAL FUNCTION getKeyByName_imm1(keyn, val, tname, ky, def, lDisp) RESULT(lerr) 2300 CHARACTER(LEN=*), INTENT(IN) :: keyn(:), tname 2301 INTEGER, ALLOCATABLE, INTENT(OUT) :: val(:) 2302 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2303 INTEGER, OPTIONAL, INTENT(IN) :: def 2304 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2305 !------------------------------------------------------------------------------------------------------------------------------ 2306 CHARACTER(LEN=maxlen) :: sval, s 2307 CHARACTER(LEN=maxlen), ALLOCATABLE :: svals(:) 2308 IF( PRESENT(def)) lerr = getKeyByName_sm11(keyn, sval, tname, ky, int2str(def), lDisp) 2309 IF(.NOT.PRESENT(def)) lerr = getKeyByName_sm11(keyn, sval, tname, ky, lDisp=lDisp) 2310 IF(lerr) RETURN 2311 lerr = strParse(sval, ',', svals) 2312 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 2313 val = str2int(svals) 2314 lerr = ANY(val == -HUGE(1)) 2315 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(tname)//' is not' 2316 CALL msg(TRIM(s)//' an integer: '//TRIM(sval), modname, lerr) 2317 END FUNCTION getKeyByName_imm1 2318 !============================================================================================================================== 2319 LOGICAL FUNCTION getKeyByName_rmm1(keyn, val, tname, ky, def, lDisp) RESULT(lerr) 2320 CHARACTER(LEN=*), INTENT(IN) :: keyn(:), tname 2321 REAL, ALLOCATABLE, INTENT(OUT) :: val(:) 2322 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2323 REAL, OPTIONAL, INTENT(IN) :: def 2324 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2325 !------------------------------------------------------------------------------------------------------------------------------ 2326 CHARACTER(LEN=maxlen) :: sval, s 2327 CHARACTER(LEN=maxlen), ALLOCATABLE :: svals(:) 2328 IF( PRESENT(def)) lerr = getKeyByName_sm11(keyn, sval, tname, ky, real2str(def), lDisp) 2329 IF(.NOT.PRESENT(def)) lerr = getKeyByName_sm11(keyn, sval, tname, ky, lDisp=lDisp) 2330 IF(lerr) RETURN 2331 lerr = strParse(sval, ',', svals) 2332 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 2333 val = str2real(svals) 2334 lerr = ANY(val == -HUGE(1.)) 2335 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(tname)//' is not' 2336 CALL msg(TRIM(s)//' a real: '//TRIM(sval), modname, lerr) 2337 END FUNCTION getKeyByName_rmm1 2338 !============================================================================================================================== 2339 LOGICAL FUNCTION getKeyByName_lmm1(keyn, val, tname, ky, def, lDisp) RESULT(lerr) 2340 CHARACTER(LEN=*), INTENT(IN) :: keyn(:), tname 2341 LOGICAL, ALLOCATABLE, INTENT(OUT) :: val(:) 2342 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2343 LOGICAL, OPTIONAL, INTENT(IN) :: def 2344 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2345 !------------------------------------------------------------------------------------------------------------------------------ 2346 CHARACTER(LEN=maxlen) :: sval, s 2347 CHARACTER(LEN=maxlen), ALLOCATABLE :: svals(:) 2348 INTEGER, ALLOCATABLE :: ivals(:) 2349 IF( PRESENT(def)) lerr = getKeyByName_sm11(keyn, sval, tname, ky, bool2str(def), lDisp) 2350 IF(.NOT.PRESENT(def)) lerr = getKeyByName_sm11(keyn, sval, tname, ky, lDisp=lDisp) 2351 IF(lerr) RETURN 2352 lerr = strParse(sval, ',', svals) 2353 IF(fmsg('can''t parse '//TRIM(sval), modname, lerr)) RETURN 2354 ivals = str2bool(svals) 2355 lerr = ANY(ivals == -1) 2356 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(tname)//' is not' 2357 CALL msg(TRIM(s)//' a boolean: '//TRIM(sval), modname, lerr) 2358 IF(.NOT.lerr) val = ivals == 1 2359 END FUNCTION getKeyByName_lmm1 2360 !============================================================================================================================== 2361 !============================================================================================================================== 2362 LOGICAL FUNCTION getKeyByName_s1mm(keyn, val, tname, ky, def, lDisp) RESULT(lerr) 2363 CHARACTER(LEN=*), INTENT(IN) :: keyn, tname(:) 2364 CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) :: val(:) 2365 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2366 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: def 2367 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2368 lerr = getKeyByName_smmm([keyn], val, tname, ky, def, lDisp) 2369 END FUNCTION getKeyByName_s1mm 2370 !============================================================================================================================== 2371 LOGICAL FUNCTION getKeyByName_i1mm(keyn, val, tname, ky, def, lDisp) RESULT(lerr) 2372 CHARACTER(LEN=*), INTENT(IN) :: keyn, tname(:) 2373 INTEGER, ALLOCATABLE, INTENT(OUT) :: val(:) 2374 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2375 INTEGER, OPTIONAL, INTENT(IN) :: def 2376 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2377 lerr = getKeyByName_immm([keyn], val, tname, ky, def, lDisp) 2378 END FUNCTION getKeyByName_i1mm 2379 !============================================================================================================================== 2380 LOGICAL FUNCTION getKeyByName_r1mm(keyn, val, tname, ky, def, lDisp) RESULT(lerr) 2381 CHARACTER(LEN=*), INTENT(IN) :: keyn, tname(:) 2382 REAL, ALLOCATABLE, INTENT(OUT) :: val(:) 2383 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2384 REAL, OPTIONAL, INTENT(IN) :: def 2385 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2386 lerr = getKeyByName_rmmm([keyn], val, tname, ky, def, lDisp) 2387 END FUNCTION getKeyByName_r1mm 2388 !============================================================================================================================== 2389 LOGICAL FUNCTION getKeyByName_l1mm(keyn, val, tname, ky, def, lDisp) RESULT(lerr) 2390 CHARACTER(LEN=*), INTENT(IN) :: keyn, tname(:) 2391 LOGICAL, ALLOCATABLE, INTENT(OUT) :: val(:) 2392 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2393 LOGICAL, OPTIONAL, INTENT(IN) :: def 2394 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2395 lerr = getKeyByName_lmmm([keyn], val, tname, ky, def, lDisp) 2396 END FUNCTION getKeyByName_l1mm 2397 !============================================================================================================================== 2398 !============================================================================================================================== 2399 LOGICAL FUNCTION getKeyByName_smmm(keyn, val, tname, ky, def, lDisp) RESULT(lerr) 2400 CHARACTER(LEN=*), INTENT(IN) :: keyn(:), tname(:) 2401 CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) :: val(:) 2402 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2403 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: def 2404 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2405 !------------------------------------------------------------------------------------------------------------------------------ 2406 CHARACTER(LEN=maxlen) :: s 1704 2407 INTEGER :: iq, nq 1705 IF(test(getKey_sm(keyn, sval, ky, nam), lerr)) RETURN 1706 nq = SIZE(sval); ALLOCATE(val(nq)) 1707 lerr = .FALSE.; DO iq=1, nq; val(iq)=str2bool(sval(iq)); END DO 1708 END FUNCTION getKey_lm 2408 LOGICAL :: lD 2409 nq = SIZE(tname); ALLOCATE(val(nq)) 2410 lD = .TRUE.; IF(PRESENT(lDisp)) lD = lDisp 2411 s = 'key "'//TRIM(strStack(keyn, '/'))//'"' 2412 lerr = .TRUE. 2413 IF(PRESENT(ky)) THEN; val = fgetKey(ky) !--- "ky" 2414 ELSE IF(ALLOCATED(tracers)) THEN; val = fgetKey(tracers(:)%keys) !--- "tracers" 2415 IF(lerr .AND. ASSOCIATED(isotope)) val = fgetKey(isotope%keys(:)) !--- "isotope" 2416 END IF 2417 IF(.NOT.PRESENT(def)) THEN; CALL msg('No '//TRIM(s)//' found', modname, lD); RETURN; END IF 2418 2419 !--- DEFAULT VALUE 2420 val = [(def, iq = 1, SIZE(tname))] 2421 CALL msg('Using defaut value for '//TRIM(s)//': '//TRIM(def), modname, lD) 2422 2423 CONTAINS 2424 2425 FUNCTION fgetKey(ky) RESULT(val) 2426 CHARACTER(LEN=maxlen), ALLOCATABLE :: val(:) 2427 TYPE(keys_type), INTENT(IN) :: ky(:) 2428 LOGICAL, ALLOCATABLE :: ler(:) 2429 lerr = SIZE(ky) == 0; IF(lerr) RETURN 2430 ALLOCATE(ler(SIZE(tname))) 2431 val = [(fgetKeyIdx(strIdx(ky(:)%name, tname(iq)), keyn, ky, ler(iq)), iq = 1, SIZE(tname))] 2432 lerr = ANY(ler) 2433 END FUNCTION fgetKey 2434 2435 END FUNCTION getKeyByName_smmm 2436 !============================================================================================================================== 2437 LOGICAL FUNCTION getKeyByName_immm(keyn, val, tname, ky, def, lDisp) RESULT(lerr) 2438 CHARACTER(LEN=*), INTENT(IN) :: keyn(:), tname(:) 2439 INTEGER, ALLOCATABLE, INTENT(OUT) :: val(:) 2440 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2441 INTEGER, OPTIONAL, INTENT(IN) :: def 2442 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2443 !------------------------------------------------------------------------------------------------------------------------------ 2444 CHARACTER(LEN=maxlen) :: s 2445 CHARACTER(LEN=maxlen), ALLOCATABLE :: svals(:) 2446 LOGICAL, ALLOCATABLE :: ll(:) 2447 IF( PRESENT(def)) lerr = getKeyByName_smmm(keyn, svals, tname, ky, int2str(def), lDisp) 2448 IF(.NOT.PRESENT(def)) lerr = getKeyByName_smmm(keyn, svals, tname, ky, lDisp=lDisp) 2449 IF(lerr) RETURN 2450 val = str2int(svals) 2451 ll = val == -HUGE(1) 2452 lerr = ANY(ll); IF(.NOT.lerr) RETURN 2453 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(strStack(tname, MASK=ll))//' is not' 2454 CALL msg(TRIM(s)//' an integer: '//TRIM(strStack(svals, MASK=ll)), modname) 2455 END FUNCTION getKeyByName_immm 2456 !============================================================================================================================== 2457 LOGICAL FUNCTION getKeyByName_rmmm(keyn, val, tname, ky, def, lDisp) RESULT(lerr) 2458 CHARACTER(LEN=*), INTENT(IN) :: keyn(:), tname(:) 2459 REAL, ALLOCATABLE, INTENT(OUT) :: val(:) 2460 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2461 REAL, OPTIONAL, INTENT(IN) :: def 2462 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2463 !------------------------------------------------------------------------------------------------------------------------------ 2464 CHARACTER(LEN=maxlen) :: s 2465 CHARACTER(LEN=maxlen), ALLOCATABLE :: svals(:) 2466 LOGICAL, ALLOCATABLE :: ll(:) 2467 IF( PRESENT(def)) lerr = getKeyByName_smmm(keyn, svals, tname, ky, real2str(def), lDisp) 2468 IF(.NOT.PRESENT(def)) lerr = getKeyByName_smmm(keyn, svals, tname, ky, lDisp=lDisp) 2469 IF(lerr) RETURN 2470 val = str2real(svals) 2471 ll = val == -HUGE(1.) 2472 lerr = ANY(ll); IF(.NOT.lerr) RETURN 2473 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(strStack(tname, MASK=ll))//' is not' 2474 CALL msg(TRIM(s)//' a real: '//TRIM(strStack(svals, MASK=ll)), modname) 2475 END FUNCTION getKeyByName_rmmm 2476 !============================================================================================================================== 2477 LOGICAL FUNCTION getKeyByName_lmmm(keyn, val, tname, ky, def, lDisp) RESULT(lerr) 2478 CHARACTER(LEN=*), INTENT(IN) :: keyn(:), tname(:) 2479 LOGICAL, ALLOCATABLE, INTENT(OUT) :: val(:) 2480 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 2481 LOGICAL, OPTIONAL, INTENT(IN) :: def 2482 LOGICAL, OPTIONAL, INTENT(IN) :: lDisp 2483 !------------------------------------------------------------------------------------------------------------------------------ 2484 CHARACTER(LEN=maxlen) :: s 2485 CHARACTER(LEN=maxlen), ALLOCATABLE :: svals(:) 2486 LOGICAL, ALLOCATABLE :: ll(:) 2487 INTEGER, ALLOCATABLE :: ivals(:) 2488 IF( PRESENT(def)) lerr = getKeyByName_smmm(keyn, svals, tname, ky, bool2str(def), lDisp) 2489 IF(.NOT.PRESENT(def)) lerr = getKeyByName_smmm(keyn, svals, tname, ky, lDisp=lDisp) 2490 IF(lerr) RETURN 2491 ivals = str2bool(svals) 2492 ll = ivals == -1 2493 lerr = ANY(ll); IF(.NOT.lerr) THEN; val = ivals == 1; RETURN; END IF 2494 s = 'key "'//TRIM(strStack(keyn, '/'))//'" of '//TRIM(strStack(tname, MASK=ll))//' is not' 2495 CALL msg(TRIM(s)//' a boolean: '//TRIM(strStack(svals, MASK=ll)), modname) 2496 END FUNCTION getKeyByName_lmmm 1709 2497 !============================================================================================================================== 1710 2498 … … 1808 2596 IF(.NOT.PRESENT(phases)) out = [( addPhase_i1(s(k), ipha, known_phases), k=1, SIZE(s) )] 1809 2597 END FUNCTION addPhase_im 2598 !============================================================================================================================== 2599 2600 2601 !============================================================================================================================== 2602 !=== APPEND TRACERS DATABASE "tracs" WITH TRACERS/KEYS "tname"/"keys" ; SAME FOR INTERNAL DATABASE "tracers" ================== 2603 !============================================================================================================================== 2604 LOGICAL FUNCTION addTracer_1(tname, keys, tracs) RESULT(lerr) 2605 CHARACTER(LEN=*), INTENT(IN) :: tname 2606 TYPE(keys_type), INTENT(IN) :: keys 2607 TYPE(trac_type), ALLOCATABLE, INTENT(INOUT) :: tracs(:) 2608 TYPE(trac_type), ALLOCATABLE :: tr(:) 2609 CHARACTER(LEN=maxlen), ALLOCATABLE :: tnames(:) 2610 INTEGER :: nt, ix 2611 IF(ALLOCATED(tracs)) THEN 2612 lerr = getKey('name', tnames, ky=tracs(:)%keys); IF(lerr) RETURN 2613 nt = SIZE(tracs) 2614 ix = strIdx(tnames, tname) 2615 CALL msg('Modifying existing tracer "'//TRIM(tname)//'"', modname, ix /= 0) 2616 CALL msg('Appending with tracer "' //TRIM(tname)//'"', modname, ix == 0) 2617 IF(ix == 0) THEN 2618 ix = nt+1; ALLOCATE(tr(nt+1)); tr(1:nt) = tracs(1:nt); CALL MOVE_ALLOC(FROM=tr, TO=tracs) 2619 END IF 2620 ELSE 2621 CALL msg('Creating a tracer descriptor with tracer "'//TRIM(tname)//'"', modname) 2622 ix = 1; ALLOCATE(tracs(1)) 2623 END IF 2624 CALL addKey('name', tname, tracs(ix)%keys) 2625 tracs(ix)%name = tname 2626 tracs(ix)%keys = keys 2627 2628 END FUNCTION addTracer_1 2629 !============================================================================================================================== 2630 LOGICAL FUNCTION addTracer_1def(tname, keys) RESULT(lerr) 2631 CHARACTER(LEN=*), INTENT(IN) :: tname 2632 TYPE(keys_type), INTENT(IN) :: keys 2633 lerr = addTracer_1(tname, keys, tracers) 2634 END FUNCTION addTracer_1def 2635 !============================================================================================================================== 2636 2637 2638 !============================================================================================================================== 2639 LOGICAL FUNCTION delTracer_1(tname, tracs) RESULT(lerr) 2640 CHARACTER(LEN=*), INTENT(IN) :: tname 2641 TYPE(trac_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: tracs(:) 2642 TYPE(trac_type), ALLOCATABLE :: tr(:) 2643 CHARACTER(LEN=maxlen), ALLOCATABLE :: tnames(:) 2644 INTEGER :: nt, ix 2645 lerr = .NOT.ALLOCATED(tracs) 2646 IF(fmsg('Can''t remove tracer "'//TRIM(tname)//'" from an empty tracers descriptor', modname, lerr)) RETURN 2647 nt = SIZE(tracs) 2648 lerr = getKey('name', tnames, ky=tracs(:)%keys); IF(lerr) RETURN 2649 ix = strIdx(tnames, tname) 2650 CALL msg('Removing tracer "' //TRIM(tname)//'"', modname, ix /= 0) 2651 CALL msg('Can''t remove unknown tracer "'//TRIM(tname)//'"', modname, ix == 0) 2652 IF(ix /= 0) THEN 2653 ALLOCATE(tr(nt-1)); tr(1:ix-1) = tracs(1:ix-1); tr(ix:nt-1) = tracs(ix+1:nt); CALL MOVE_ALLOC(FROM=tr, TO=tracs) 2654 END IF 2655 END FUNCTION delTracer_1 2656 !============================================================================================================================== 2657 LOGICAL FUNCTION delTracer_1def(tname) RESULT(lerr) 2658 CHARACTER(LEN=*), INTENT(IN) :: tname 2659 lerr = delTracer(tname, tracers) 2660 END FUNCTION delTracer_1def 1810 2661 !============================================================================================================================== 1811 2662 … … 1908 2759 !============================================================================================================================== 1909 2760 1910 1911 !==============================================================================================================================1912 !=== GET THE NAME(S) OF THE ANCESTOR(S) OF TRACER(S) "tname" AT GENERATION "igen" IN THE TRACERS DESCRIPTORS LIST "tr" =======1913 !==============================================================================================================================1914 SUBROUTINE ancestor_1(t, out, tname, igen)1915 TYPE(trac_type), INTENT(IN) :: t(:)1916 CHARACTER(LEN=maxlen), INTENT(OUT) :: out1917 CHARACTER(LEN=*), INTENT(IN) :: tname1918 INTEGER, OPTIONAL, INTENT(IN) :: igen1919 !------------------------------------------------------------------------------------------------------------------------------1920 INTEGER :: ix1921 CALL idxAncestor_1(t, ix, tname, igen)1922 out = ''; IF(ix /= 0) out = t(ix)%name1923 END SUBROUTINE ancestor_11924 !==============================================================================================================================1925 SUBROUTINE ancestor_mt(t, out, tname, igen)1926 TYPE(trac_type), INTENT(IN) :: t(:)1927 CHARACTER(LEN=*), INTENT(IN) :: tname(:)1928 CHARACTER(LEN=maxlen), INTENT(OUT) :: out(SIZE(tname))1929 INTEGER, OPTIONAL, INTENT(IN) :: igen1930 !------------------------------------------------------------------------------------------------------------------------------1931 INTEGER :: ix(SIZE(tname))1932 CALL idxAncestor_mt(t, ix, tname, igen)1933 out(:) = ''; WHERE(ix /= 0) out = t(ix)%name1934 END SUBROUTINE ancestor_mt1935 !==============================================================================================================================1936 SUBROUTINE ancestor_m(t, out, igen)1937 TYPE(trac_type), INTENT(IN) :: t(:)1938 CHARACTER(LEN=maxlen), INTENT(OUT) :: out(SIZE(t))1939 INTEGER, OPTIONAL, INTENT(IN) :: igen1940 !------------------------------------------------------------------------------------------------------------------------------1941 INTEGER :: ix(SIZE(t))1942 CALL idxAncestor_m(t, ix, igen)1943 out(:) = ''; WHERE(ix /= 0) out = t(ix)%name1944 END SUBROUTINE ancestor_m1945 !==============================================================================================================================1946 1947 1948 !==============================================================================================================================1949 !=== GET THE INDEX(ES) OF THE GENERATION "igen" ANCESTOR(S) OF "tname" (t%name IF UNSPECIFIED) IN THE "t" LIST ================1950 !==============================================================================================================================1951 SUBROUTINE idxAncestor_1(t, idx, tname, igen)1952 TYPE(trac_type), INTENT(IN) :: t(:)1953 INTEGER, INTENT(OUT) :: idx1954 CHARACTER(LEN=*), INTENT(IN) :: tname1955 INTEGER, OPTIONAL, INTENT(IN) :: igen1956 INTEGER :: ig1957 ig = 0; IF(PRESENT(igen)) ig = igen1958 idx = strIdx(t(:)%name, tname)1959 IF(idx == 0) RETURN !--- Tracer not found1960 IF(t(idx)%iGeneration <= ig) RETURN !--- Tracer has a lower generation number than asked generation 'igen"1961 DO WHILE(t(idx)%iGeneration > ig); idx = strIdx(t(:)%name, t(idx)%parent); END DO1962 END SUBROUTINE idxAncestor_11963 !------------------------------------------------------------------------------------------------------------------------------1964 SUBROUTINE idxAncestor_mt(t, idx, tname, igen)1965 TYPE(trac_type), INTENT(IN) :: t(:)1966 CHARACTER(LEN=*), INTENT(IN) :: tname(:)1967 INTEGER, INTENT(OUT) :: idx(SIZE(tname))1968 INTEGER, OPTIONAL, INTENT(IN) :: igen1969 INTEGER :: ix1970 DO ix = 1, SIZE(tname); CALL idxAncestor_1(t, idx(ix), tname(ix), igen); END DO1971 END SUBROUTINE idxAncestor_mt1972 !------------------------------------------------------------------------------------------------------------------------------1973 SUBROUTINE idxAncestor_m(t, idx, igen)1974 TYPE(trac_type), INTENT(IN) :: t(:)1975 INTEGER, INTENT(OUT) :: idx(SIZE(t))1976 INTEGER, OPTIONAL, INTENT(IN) :: igen1977 INTEGER :: ix1978 DO ix = 1, SIZE(t); CALL idxAncestor_1(t, idx(ix), t(ix)%name, igen); END DO1979 END SUBROUTINE idxAncestor_m1980 !==============================================================================================================================1981 1982 1983 2761 END MODULE readTracFiles_mod -
LMDZ6/branches/cirrus/libf/misc/strings_mod.F90
r4454 r5202 10 10 PUBLIC :: is_numeric, bool2str, int2str, real2str, dble2str 11 11 PUBLIC :: reduceExpr, str2bool, str2int, str2real, str2dble 12 PUBLIC :: addQuotes, checkList, removeComment , test12 PUBLIC :: addQuotes, checkList, removeComment 13 13 14 14 INTERFACE get_in; MODULE PROCEDURE getin_s, getin_i, getin_r, getin_l; END INTERFACE get_in … … 22 22 INTERFACE strCount; MODULE PROCEDURE strCount_m1, strCount_11, strCount_1m; END INTERFACE strCount 23 23 INTERFACE strReplace; MODULE PROCEDURE strReplace_1, strReplace_m; END INTERFACE strReplace 24 INTERFACE cat; MODULE PROCEDURE horzcat_s1, horzcat_i1, horzcat_r1, & 25 ! horzcat_d1, horzcat_dm, 26 horzcat_sm, horzcat_im, horzcat_rm; END INTERFACE cat 27 INTERFACE find; MODULE PROCEDURE strFind, find_int, find_boo; END INTERFACE find 24 INTERFACE cat; MODULE PROCEDURE horzcat_s00, horzcat_i00, horzcat_r00, & !horzcat_d00, & 25 horzcat_s10, horzcat_i10, horzcat_r10, & !horzcat_d10, & 26 horzcat_s11, horzcat_i11, horzcat_r11, & !horzcat_d11, & 27 horzcat_s21, horzcat_i21, horzcat_r21; END INTERFACE cat !horzcat_d21 28 INTERFACE strFind; MODULE PROCEDURE strFind_1, strFind_m; END INTERFACE strFind 29 INTERFACE find; MODULE PROCEDURE strFind_1, strFind_m, intFind_1, intFind_m, booFind; END INTERFACE find 28 30 INTERFACE dispOutliers; MODULE PROCEDURE dispOutliers_1, dispOutliers_2; END INTERFACE dispOutliers 29 31 INTERFACE reduceExpr; MODULE PROCEDURE reduceExpr_1, reduceExpr_m; END INTERFACE reduceExpr … … 36 38 CONTAINS 37 39 38 !==============================================================================================================================39 LOGICAL FUNCTION test(lcond, lout) RESULT(lerr)40 LOGICAL, INTENT(IN) :: lcond41 LOGICAL, INTENT(OUT) :: lout42 lerr = lcond; lout = lcond43 END FUNCTION test44 !==============================================================================================================================45 46 40 47 41 !============================================================================================================================== 48 42 SUBROUTINE init_printout(lunout_, prt_level_) 43 IMPLICIT NONE 49 44 INTEGER, INTENT(IN) :: lunout_, prt_level_ 50 45 lunout = lunout_ … … 58 53 !============================================================================================================================== 59 54 SUBROUTINE getin_s(nam, val, def) 60 USE ioipsl_getincom, ONLY: getin 55 USE ioipsl_getincom, ONLY: getin 56 IMPLICIT NONE 61 57 CHARACTER(LEN=*), INTENT(IN) :: nam 62 58 CHARACTER(LEN=*), INTENT(INOUT) :: val … … 67 63 !============================================================================================================================== 68 64 SUBROUTINE getin_i(nam, val, def) 69 USE ioipsl_getincom, ONLY: getin 65 USE ioipsl_getincom, ONLY: getin 66 IMPLICIT NONE 70 67 CHARACTER(LEN=*), INTENT(IN) :: nam 71 68 INTEGER, INTENT(INOUT) :: val … … 76 73 !============================================================================================================================== 77 74 SUBROUTINE getin_r(nam, val, def) 78 USE ioipsl_getincom, ONLY: getin 75 USE ioipsl_getincom, ONLY: getin 76 IMPLICIT NONE 79 77 CHARACTER(LEN=*), INTENT(IN) :: nam 80 78 REAL, INTENT(INOUT) :: val … … 85 83 !============================================================================================================================== 86 84 SUBROUTINE getin_l(nam, val, def) 87 USE ioipsl_getincom, ONLY: getin 85 USE ioipsl_getincom, ONLY: getin 86 IMPLICIT NONE 88 87 CHARACTER(LEN=*), INTENT(IN) :: nam 89 88 LOGICAL, INTENT(INOUT) :: val … … 99 98 !============================================================================================================================== 100 99 SUBROUTINE msg_1(str, modname, ll, unit) 100 IMPLICIT NONE 101 101 !--- Display a simple message "str". Optional parameters: 102 102 ! * "modname": module name, displayed in front of the message (with ": " separator) if present. … … 118 118 !============================================================================================================================== 119 119 SUBROUTINE msg_m(str, modname, ll, unit, nmax) 120 IMPLICIT NONE 120 121 !--- Same as msg_1 with multiple strings that are stacked (separator: coma) on up to "nmax" full lines. 121 122 CHARACTER(LEN=*), INTENT(IN) :: str(:) … … 138 139 !============================================================================================================================== 139 140 LOGICAL FUNCTION fmsg_1(str, modname, ll, unit) RESULT(l) 141 IMPLICIT NONE 140 142 CHARACTER(LEN=*), INTENT(IN) :: str 141 143 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: modname … … 152 154 !============================================================================================================================== 153 155 LOGICAL FUNCTION fmsg_m(str, modname, ll, unit, nmax) RESULT(l) 156 IMPLICIT NONE 154 157 CHARACTER(LEN=*), INTENT(IN) :: str(:) 155 158 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: modname … … 173 176 !============================================================================================================================== 174 177 ELEMENTAL CHARACTER(LEN=maxlen) FUNCTION strLower(str) RESULT(out) 178 IMPLICIT NONE 175 179 CHARACTER(LEN=*), INTENT(IN) :: str 176 180 INTEGER :: k … … 182 186 !============================================================================================================================== 183 187 ELEMENTAL CHARACTER(LEN=maxlen) FUNCTION strUpper(str) RESULT(out) 188 IMPLICIT NONE 184 189 CHARACTER(LEN=*), INTENT(IN) :: str 185 190 INTEGER :: k … … 199 204 !============================================================================================================================== 200 205 CHARACTER(LEN=maxlen) FUNCTION strHead_1(str, sep, lBackward) RESULT(out) 206 IMPLICIT NONE 201 207 CHARACTER(LEN=*), INTENT(IN) :: str 202 208 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep … … 214 220 !============================================================================================================================== 215 221 FUNCTION strHead_m(str, sep, lBackward) RESULT(out) 222 IMPLICIT NONE 216 223 CHARACTER(LEN=maxlen), ALLOCATABLE :: out(:) 217 224 CHARACTER(LEN=*), INTENT(IN) :: str(:) … … 235 242 !============================================================================================================================== 236 243 CHARACTER(LEN=maxlen) FUNCTION strTail_1(str, sep, lBackWard) RESULT(out) 244 IMPLICIT NONE 237 245 CHARACTER(LEN=*), INTENT(IN) :: str 238 246 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep … … 250 258 !============================================================================================================================== 251 259 FUNCTION strTail_m(str, sep, lBackWard) RESULT(out) 260 IMPLICIT NONE 252 261 CHARACTER(LEN=maxlen), ALLOCATABLE :: out(:) 253 262 CHARACTER(LEN=*), INTENT(IN) :: str(:) … … 271 280 !============================================================================================================================== 272 281 FUNCTION strStack(str, sep, mask) RESULT(out) 282 IMPLICIT NONE 273 283 CHARACTER(LEN=:), ALLOCATABLE :: out 274 284 CHARACTER(LEN=*), INTENT(IN) :: str(:) … … 292 302 !============================================================================================================================== 293 303 FUNCTION strStackm(str, sep, nmax) RESULT(out) 304 IMPLICIT NONE 294 305 CHARACTER(LEN=maxlen), ALLOCATABLE :: out(:) 295 306 CHARACTER(LEN=*), INTENT(IN) :: str(:) … … 324 335 !============================================================================================================================== 325 336 SUBROUTINE strClean_1(str) 337 IMPLICIT NONE 326 338 CHARACTER(LEN=*), INTENT(INOUT) :: str 327 339 INTEGER :: k, n, m … … 337 349 !============================================================================================================================== 338 350 SUBROUTINE strClean_m(str) 351 IMPLICIT NONE 339 352 CHARACTER(LEN=*), INTENT(INOUT) :: str(:) 340 353 INTEGER :: k … … 349 362 !============================================================================================================================== 350 363 SUBROUTINE strReduce_1(str, nb) 364 IMPLICIT NONE 351 365 CHARACTER(LEN=*), ALLOCATABLE, INTENT(INOUT) :: str(:) 352 366 INTEGER, OPTIONAL, INTENT(OUT) :: nb … … 366 380 !============================================================================================================================== 367 381 SUBROUTINE strReduce_2(str1, str2) 382 IMPLICIT NONE 368 383 CHARACTER(LEN=*), ALLOCATABLE, INTENT(INOUT) :: str1(:) 369 384 CHARACTER(LEN=*), INTENT(IN) :: str2(:) … … 392 407 !============================================================================================================================== 393 408 INTEGER FUNCTION strIdx_1(str, s) RESULT(out) 409 IMPLICIT NONE 394 410 CHARACTER(LEN=*), INTENT(IN) :: str(:), s 395 411 DO out = 1, SIZE(str); IF(str(out) == s) EXIT; END DO … … 398 414 !============================================================================================================================== 399 415 FUNCTION strIdx_m(str, s, n) RESULT(out) 416 IMPLICIT NONE 400 417 CHARACTER(LEN=*), INTENT(IN) :: str(:), s(:) 401 418 INTEGER, OPTIONAL, INTENT(OUT) :: n … … 412 429 !=== GET THE INDEX LIST OF THE ELEMENTS OF "str(:)" EQUAL TO "s" AND OPTIONALY, ITS LENGTH "n" ================================ 413 430 !============================================================================================================================== 414 FUNCTION strFind(str, s, n) RESULT(out) 431 FUNCTION strFind_1(str, s, n) RESULT(out) 432 IMPLICIT NONE 415 433 CHARACTER(LEN=*), INTENT(IN) :: str(:), s 416 434 INTEGER, OPTIONAL, INTENT(OUT) :: n … … 420 438 out = PACK( [(k, k=1, SIZE(str(:), DIM=1))], MASK = str(:) == s ) 421 439 IF(PRESENT(n)) n = SIZE(out(:), DIM=1) 422 END FUNCTION strFind 423 !============================================================================================================================== 424 FUNCTION find_int(i,j,n) RESULT(out) 440 END FUNCTION strFind_1 441 !============================================================================================================================== 442 FUNCTION strFind_m(str, s, n) RESULT(out) 443 IMPLICIT NONE 444 CHARACTER(LEN=*), INTENT(IN) :: str(:), s(:) 445 INTEGER, OPTIONAL, INTENT(OUT) :: n 446 INTEGER, ALLOCATABLE :: out(:) 447 !------------------------------------------------------------------------------------------------------------------------------ 448 INTEGER :: k 449 out = [(strFind_1(str, s(k)), k=1, SIZE(s))] 450 IF(PRESENT(n)) n = SIZE(out(:), DIM=1) 451 END FUNCTION strFind_m 452 !============================================================================================================================== 453 FUNCTION intFind_1(i,j,n) RESULT(out) 454 IMPLICIT NONE 425 455 INTEGER, INTENT(IN) :: i(:), j 426 456 INTEGER, OPTIONAL, INTENT(OUT) :: n … … 430 460 out = PACK( [(k, k=1, SIZE(i(:), DIM=1))], MASK = i(:) == j ) 431 461 IF(PRESENT(n)) n = SIZE(out(:), DIM=1) 432 END FUNCTION find_int 433 !============================================================================================================================== 434 FUNCTION find_boo(l,n) RESULT(out) 435 LOGICAL, INTENT(IN) :: l(:) 462 END FUNCTION intFind_1 463 !============================================================================================================================== 464 FUNCTION intFind_m(i,j,n) RESULT(out) 465 IMPLICIT NONE 466 INTEGER, INTENT(IN) :: i(:), j(:) 467 INTEGER, OPTIONAL, INTENT(OUT) :: n 468 INTEGER, ALLOCATABLE :: out(:) 469 !------------------------------------------------------------------------------------------------------------------------------ 470 INTEGER :: k 471 out = [(intFind_1(i, j(k)), k=1, SIZE(j))] 472 IF(PRESENT(n)) n = SIZE(out(:), DIM=1) 473 END FUNCTION intFind_m 474 !============================================================================================================================== 475 FUNCTION booFind(l,n) RESULT(out) 476 IMPLICIT NONE 477 LOGICAL, INTENT(IN) :: l(:) 436 478 INTEGER, OPTIONAL, INTENT(OUT) :: n 437 479 INTEGER, ALLOCATABLE :: out(:) … … 440 482 out = PACK( [(k, k=1, SIZE(l(:), DIM=1))], MASK = l(:) ) 441 483 IF(PRESENT(n)) n = SIZE(out(:), DIM=1) 442 END FUNCTION find_boo484 END FUNCTION booFind 443 485 !============================================================================================================================== 444 486 … … 450 492 !============================================================================================================================== 451 493 LOGICAL FUNCTION strIdx_prv(rawList, del, ibeg, idx, idel, lSc) RESULT(lerr) 494 IMPLICIT NONE 452 495 CHARACTER(LEN=*), INTENT(IN) :: rawList !--- String in which delimiters have to be identified 453 496 CHARACTER(LEN=*), INTENT(IN) :: del(:) !--- List of delimiters … … 469 512 END IF 470 513 471 IF(test(idx == 1 .AND. INDEX('+-',del(idel)) /= 0, lerr)) RETURN!--- The front delimiter is different from +/-: error472 IF( idx /= 1 .AND. is_numeric(rawList(ibeg:idx-1))) RETURN!--- The input string head is a valid number514 lerr = idx == 1 .AND. INDEX('+-',del(idel)) /= 0; IF(lerr) RETURN !--- The front delimiter is different from +/-: error 515 IF( idx /= 1 .AND. is_numeric(rawList(ibeg:idx-1))) RETURN !--- The input string head is a valid number 473 516 474 517 !=== The string part in front of the 1st delimiter is not a valid number: search for next delimiter index "idx" … … 503 546 !============================================================================================================================== 504 547 LOGICAL FUNCTION strCount_11(rawList, delimiter, nb, lSc) RESULT(lerr) 548 IMPLICIT NONE 505 549 CHARACTER(LEN=*), INTENT(IN) :: rawList 506 550 CHARACTER(LEN=*), INTENT(IN) :: delimiter … … 514 558 !============================================================================================================================== 515 559 LOGICAL FUNCTION strCount_m1(rawList, delimiter, nb, lSc) RESULT(lerr) 560 IMPLICIT NONE 516 561 CHARACTER(LEN=*), INTENT(IN) :: rawList(:) 517 562 CHARACTER(LEN=*), INTENT(IN) :: delimiter … … 530 575 !============================================================================================================================== 531 576 LOGICAL FUNCTION strCount_1m(rawList, delimiter, nb, lSc) RESULT(lerr) 577 IMPLICIT NONE 532 578 CHARACTER(LEN=*), INTENT(IN) :: rawList 533 579 CHARACTER(LEN=*), INTENT(IN) :: delimiter(:) … … 560 606 !============================================================================================================================== 561 607 LOGICAL FUNCTION strParse(rawList, delimiter, keys, n, vals) RESULT(lerr) 608 IMPLICIT NONE 562 609 CHARACTER(LEN=*), INTENT(IN) :: rawList, delimiter 563 610 CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) :: keys(:) … … 570 617 r = TRIM(ADJUSTL(rawList)) 571 618 nr = LEN_TRIM(r); IF(nr == 0) THEN; keys = ['']; RETURN; END IF 572 CALL strParse_prv(nk) !--- COUNT THE ELEMENTS 573 ALLOCATE(keys(nk)) 574 IF(PRESENT(vals)) THEN 575 ALLOCATE(vals(nk)); CALL strParse_prv(nk, keys, vals) !--- PARSE THE KEYS 576 ELSE 577 CALL strParse_prv(nk, keys) !--- PARSE THE KEYS 578 END IF 579 IF(PRESENT(n)) n = nk 619 nk = countK() !--- COUNT THE ELEMENTS 620 CALL parseK(keys) !--- PARSE THE KEYS 621 IF(PRESENT(vals)) CALL parseV(vals) !--- PARSE <key>=<val> PAIRS 622 IF(PRESENT(n)) n = nk !--- RETURN THE NUMBER OF KEYS 580 623 581 624 CONTAINS 582 625 583 626 !------------------------------------------------------------------------------------------------------------------------------ 584 SUBROUTINE strParse_prv(nkeys, keys, vals) 585 !--- * Get the number of elements after parsing ("nkeys" only is present) 586 !--- * Parse the <key>=<val> pairs and store result in "keys" and "vals" (already allocated) 587 IMPLICIT NONE 588 INTEGER, INTENT(OUT) :: nkeys 589 CHARACTER(LEN=maxlen), OPTIONAL, INTENT(OUT) :: keys(:) 590 CHARACTER(LEN=maxlen), OPTIONAL, INTENT(OUT) :: vals(:) 591 !------------------------------------------------------------------------------------------------------------------------------ 592 INTEGER :: ib, ie 593 nkeys = 1; ib = 1 627 INTEGER FUNCTION countK() RESULT(nkeys) 628 !--- Get the number of elements after parsing. 629 IMPLICIT NONE 630 !------------------------------------------------------------------------------------------------------------------------------ 631 INTEGER :: ib, ie, nl 632 nkeys = 1; ib = 1; nl = LEN(delimiter) 594 633 DO 595 634 ie = INDEX(rawList(ib:nr), delimiter)+ib-1 !--- Determine the next separator start index 596 635 IF(ie == ib-1) EXIT 597 IF(PRESENT(keys)) keys(nkeys) = r(ib:ie-1) !--- Get the ikth key 598 IF(PRESENT(vals)) CALL parseKeys(keys(nkeys), vals(nkeys)) !--- Parse the ikth <key>=<val> pair 636 ib = ie + nl 637 DO WHILE(ANY([0, 9, 32] == IACHAR(r(ib:ib))) .AND. ib < nr) !--- Skip blanks (ascii): NULL (0), TAB (9), SPACE (32) 638 ib = ib + 1 639 END DO !--- Skip spaces before next chain 640 nkeys = nkeys+1 641 END DO 642 END FUNCTION countK 643 644 !------------------------------------------------------------------------------------------------------------------------------ 645 SUBROUTINE parseK(keys) 646 !--- Parse the string separated by "delimiter" from "rawList" into "keys(:)" 647 IMPLICIT NONE 648 CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) :: keys(:) 649 !------------------------------------------------------------------------------------------------------------------------------ 650 INTEGER :: ib, ie, ik 651 ALLOCATE(keys(nk)) 652 ib = 1 653 DO ik = 1, nk 654 ie = INDEX(rawList(ib:nr), delimiter)+ib-1 !--- Determine the next separator start index 655 IF(ie == ib-1) EXIT 656 keys(ik) = r(ib:ie-1) !--- Get the ikth key 599 657 ib = ie + LEN(delimiter) 600 658 DO WHILE(r(ib:ib) == ' ' .AND. ib < nr); ib = ib + 1; END DO !--- Skip spaces before next chain 601 nkeys = nkeys+1 602 END DO 603 IF(PRESENT(keys)) keys(nkeys) = r(ib:nr) !--- Get the last key 604 IF(PRESENT(vals)) CALL parseKeys(keys(nkeys), vals(nkeys)) !--- Parse the last <key>=<val> pair 605 END SUBROUTINE strParse_prv 606 607 !------------------------------------------------------------------------------------------------------------------------------ 608 SUBROUTINE parseKeys(key, val) 609 CHARACTER(LEN=*), INTENT(INOUT) :: key 610 CHARACTER(LEN=*), INTENT(OUT) :: val 611 !------------------------------------------------------------------------------------------------------------------------------ 612 INTEGER :: ix 613 ix = INDEX(key, '='); IF(ix == 0) RETURN !--- First "=" index in "key" 614 val = ADJUSTL(key(ix+1:LEN_TRIM(key))) 615 key = ADJUSTL(key(1:ix-1)) 616 END SUBROUTINE parseKeys 659 END DO 660 keys(ik) = r(ib:nr) !--- Get the last key 661 END SUBROUTINE parseK 662 663 !------------------------------------------------------------------------------------------------------------------------------ 664 SUBROUTINE parseV(vals) 665 !--- Parse the <key>=<val> pairs in "keys(:)" into "keys" and "vals" 666 IMPLICIT NONE 667 CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) :: vals(:) 668 !------------------------------------------------------------------------------------------------------------------------------ 669 CHARACTER(LEN=maxlen) :: key 670 INTEGER :: ik, ix 671 ALLOCATE(vals(nk)) 672 DO ik = 1, nk; key = keys(ik) 673 vals(ik) = '' 674 ix = INDEX(key, '='); IF(ix == 0) CYCLE !--- First "=" index in "key" 675 vals(ik) = ADJUSTL(key(ix+1:LEN_TRIM(key))) 676 keys(ik) = ADJUSTL(key(1:ix-1)) 677 END DO 678 END SUBROUTINE parseV 617 679 618 680 END FUNCTION strParse 619 681 !============================================================================================================================== 620 682 LOGICAL FUNCTION strParse_m(rawList, delimiter, keys, n, vals, lSc, id) RESULT(lerr) 683 IMPLICIT NONE 621 684 CHARACTER(LEN=*), INTENT(IN) :: rawList, delimiter(:) 622 685 CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) :: keys(:) !--- Parsed keys vector … … 630 693 LOGICAL :: ll 631 694 ll = .FALSE.; IF(PRESENT(lSc)) ll = lSc 632 IF(test(fmsg("Couldn't parse list: non-numerical strings were found", ll=strCount_1m(rawList, delimiter, nk, ll)),lerr)) RETURN 695 lerr = strCount_1m(rawList, delimiter, nk, ll) 696 CALL msg("Couldn't parse list: non-numerical strings were found", ll=lerr); IF(lerr) RETURN 633 697 634 698 !--- FEW ALLOCATIONS … … 643 707 ib = 1 644 708 DO ik = 1, nk-1 645 IF(test(fmsg('Non-numeric values found', ll=strIdx_prv(r, delimiter, ib, ie, jd, ll)),lerr)) RETURN 709 lerr = strIdx_prv(r, delimiter, ib, ie, jd, ll) 710 CALL msg('Non-numeric values found', ll=lerr); IF(lerr) RETURN 646 711 keys(ik) = r(ib:ie-1) 647 712 IF(PRESENT(vals)) CALL parseKeys(keys(ik), vals(ik)) !--- Parse a <key>=<val> pair … … 657 722 !------------------------------------------------------------------------------------------------------------------------------ 658 723 SUBROUTINE parseKeys(key, val) 724 IMPLICIT NONE 659 725 CHARACTER(LEN=*), INTENT(INOUT) :: key 660 726 CHARACTER(LEN=*), INTENT(OUT) :: val … … 674 740 !============================================================================================================================== 675 741 SUBROUTINE strReplace_1(str, key, val, lsurr) 742 IMPLICIT NONE 676 743 CHARACTER(LEN=*), INTENT(INOUT) :: str !--- Main string 677 744 CHARACTER(LEN=*), INTENT(IN) :: key, val !--- "key" will be replaced by "val" … … 700 767 !============================================================================================================================== 701 768 SUBROUTINE strReplace_m(str, key, val, lsurr) 769 IMPLICIT NONE 702 770 CHARACTER(LEN=*), INTENT(INOUT) :: str(:) !--- Main strings vector 703 771 CHARACTER(LEN=*), INTENT(IN) :: key, val !--- "key" will be replaced by "val" … … 714 782 !=== Contatenate horizontally scalars/vectors of strings/integers/reals into a vector/array =================================== 715 783 !============================================================================================================================== 716 FUNCTION horzcat_s1(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9) RESULT(out) 717 CHARACTER(LEN=*), TARGET, INTENT(IN) :: s0 784 FUNCTION horzcat_s00(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9) RESULT(out) 785 IMPLICIT NONE 786 CHARACTER(LEN=*), INTENT(IN) :: s0 718 787 CHARACTER(LEN=*), OPTIONAL, TARGET, INTENT(IN) :: s1, s2, s3, s4, s5, s6, s7, s8, s9 719 788 CHARACTER(LEN=maxlen), ALLOCATABLE :: out(:) 720 !------------------------------------------------------------------------------------------------------------------------------721 789 CHARACTER(LEN=maxlen), POINTER :: s 722 LOGICAL :: lv(10) 723 INTEGER :: iv 724 lv = [ .TRUE. , PRESENT(s1), PRESENT(s2), PRESENT(s3), PRESENT(s4) , & 725 PRESENT(s5), PRESENT(s6), PRESENT(s7), PRESENT(s8), PRESENT(s9) ] 726 ALLOCATE(out(COUNT(lv))) 727 DO iv=1, COUNT(lv) 728 SELECT CASE(iv) 729 CASE(1); s=> s0; CASE(2); s=> s1; CASE(3); s=> s2; CASE(4); s=> s3; CASE(5); s=> s4 730 CASE(6); s=> s5; CASE(7); s=> s6; CASE(8); s=> s7; CASE(9); s=> s8; CASE(10);s=> s9 790 INTEGER :: nrow, iv 791 LOGICAL :: pre(9) 792 !------------------------------------------------------------------------------------------------------------------------------ 793 pre(:) = [PRESENT(s1),PRESENT(s2),PRESENT(s3),PRESENT(s4),PRESENT(s5),PRESENT(s6),PRESENT(s7),PRESENT(s8),PRESENT(s9)] 794 nrow = 1+COUNT(pre) 795 ALLOCATE(out(nrow)) 796 out(1) = s0 797 DO iv = 2, nrow; IF(.NOT.pre(iv-1)) CYCLE 798 SELECT CASE(iv-1) 799 CASE(1); s=> s1; CASE(2); s=> s2; CASE(3); s=> s3; CASE(4); s=> s4; CASE(5); s=> s5 800 CASE(6); s=> s6; CASE(7); s=> s7; CASE(8); s=> s8; CASE(9); s=> s9 731 801 END SELECT 732 802 out(iv) = s 733 803 END DO 734 END FUNCTION horzcat_s1 735 !============================================================================================================================== 736 FUNCTION horzcat_sm(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9) RESULT(out) 737 CHARACTER(LEN=*), TARGET, DIMENSION(:), INTENT(IN) :: s0 738 CHARACTER(LEN=*), OPTIONAL, TARGET, DIMENSION(:), INTENT(IN) :: s1, s2, s3, s4, s5, s6, s7, s8, s9 804 END FUNCTION horzcat_s00 805 !============================================================================================================================== 806 FUNCTION horzcat_s10(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9) RESULT(out) 807 IMPLICIT NONE 808 CHARACTER(LEN=*), INTENT(IN) :: s0(:), s1 809 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: s2, s3, s4, s5, s6, s7, s8, s9 810 CHARACTER(LEN=maxlen), ALLOCATABLE :: out(:), tmp(:) 811 INTEGER :: nc 812 nc = SIZE(s0) 813 tmp = horzcat_s00(s0(nc), s1, s2, s3, s4, s5, s6, s7, s8, s9) 814 IF(nc == 1) out = tmp 815 IF(nc /= 1) out = [s0(1:nc-1), tmp] 816 END FUNCTION horzcat_s10 817 !============================================================================================================================== 818 FUNCTION horzcat_s11(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9) RESULT(out) 819 IMPLICIT NONE 820 CHARACTER(LEN=*), INTENT(IN) :: s0(:) 821 CHARACTER(LEN=*), OPTIONAL, TARGET, INTENT(IN) :: s1(:), s2(:), s3(:), s4(:), s5(:), s6(:), s7(:), s8(:), s9(:) 739 822 CHARACTER(LEN=maxlen), ALLOCATABLE :: out(:,:) 740 !------------------------------------------------------------------------------------------------------------------------------741 823 CHARACTER(LEN=maxlen), POINTER :: s(:) 742 LOGICAL :: lv(10) 743 INTEGER :: nrow, ncol, iv, n 744 lv = [ .TRUE. , PRESENT(s1), PRESENT(s2), PRESENT(s3), PRESENT(s4) , & 745 PRESENT(s5), PRESENT(s6), PRESENT(s7), PRESENT(s8), PRESENT(s9) ] 746 nrow = SIZE(s0); ncol=COUNT(lv) 824 INTEGER :: nrow, ncol, iv, n 825 LOGICAL :: pre(9) 826 !------------------------------------------------------------------------------------------------------------------------------ 827 pre(:) = [PRESENT(s1),PRESENT(s2),PRESENT(s3),PRESENT(s4),PRESENT(s5),PRESENT(s6),PRESENT(s7),PRESENT(s8),PRESENT(s9)] 828 nrow = SIZE(s0) 829 ncol = 1+COUNT(pre) 747 830 ALLOCATE(out(nrow, ncol)) 748 DO iv=1, ncol 749 SELECT CASE(iv) 750 CASE(1); s=> s0; CASE(2); s=> s1; CASE(3); s=> s2; CASE(4); s=> s3; CASE(5); s=> s4 751 CASE(6); s=> s5; CASE(7); s=> s6; CASE(8); s=> s7; CASE(9); s=> s8; CASE(10);s=> s9 831 out(:,1) = s0 832 DO iv = 2, ncol; IF(.NOT.pre(iv-1)) CYCLE 833 SELECT CASE(iv-1) 834 CASE(1); s=> s1; CASE(2); s=> s2; CASE(3); s=> s3; CASE(4); s=> s4; CASE(5); s=> s5 835 CASE(6); s=> s6; CASE(7); s=> s7; CASE(8); s=> s8; CASE(9); s=> s9 752 836 END SELECT 753 837 n = SIZE(s, DIM=1) 754 IF(n /=nrow) THEN; CALL msg("Can't concatenate vectors of differing lengths"); STOP; END IF838 IF(n /= nrow) THEN; CALL msg("Can't concatenate vectors of differing lengths"); STOP; END IF 755 839 out(:,iv) = s(:) 756 840 END DO 757 END FUNCTION horzcat_sm 758 !============================================================================================================================== 759 FUNCTION horzcat_i1(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9) RESULT(out) 760 INTEGER, TARGET, INTENT(IN) :: i0 841 END FUNCTION horzcat_s11 842 !============================================================================================================================== 843 FUNCTION horzcat_s21(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9) RESULT(out) 844 IMPLICIT NONE 845 CHARACTER(LEN=*), INTENT(IN) :: s0(:,:), s1(:) 846 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: s2(:), s3(:), s4(:), s5(:), s6(:), s7(:), s8(:), s9(:) 847 CHARACTER(LEN=maxlen), ALLOCATABLE :: out(:,:), tmp(:,:) 848 INTEGER :: nc 849 nc = SIZE(s0, 2) 850 tmp = horzcat_s11(s0(:,nc), s1, s2, s3, s4, s5, s6, s7, s8, s9) 851 IF(nc == 1) out = tmp 852 IF(nc /= 1) out = RESHAPE([PACK(s0(:,1:nc-1), .TRUE.), PACK(tmp, .TRUE.)], SHAPE=[SIZE(s0, 1), nc + SIZE(tmp, 2)-1]) 853 END FUNCTION horzcat_s21 854 !============================================================================================================================== 855 FUNCTION horzcat_i00(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9) RESULT(out) 856 IMPLICIT NONE 857 INTEGER, INTENT(IN) :: i0 761 858 INTEGER, OPTIONAL, TARGET, INTENT(IN) :: i1, i2, i3, i4, i5, i6, i7, i8, i9 762 859 INTEGER, ALLOCATABLE :: out(:) 763 !------------------------------------------------------------------------------------------------------------------------------764 860 INTEGER, POINTER :: i 765 LOGICAL :: lv(10) 766 INTEGER :: iv 767 lv = [ .TRUE. , PRESENT(i1), PRESENT(i2), PRESENT(i3), PRESENT(i4) , & 768 PRESENT(i5), PRESENT(i6), PRESENT(i7), PRESENT(i8), PRESENT(i9) ] 769 ALLOCATE(out(COUNT(lv))) 770 DO iv=1, COUNT(lv) 771 SELECT CASE(iv) 772 CASE(1); i=> i0; CASE(2); i=> i1; CASE(3); i=> i2; CASE(4); i=> i3; CASE(5); i=> i4 773 CASE(6); i=> i5; CASE(7); i=> i6; CASE(8); i=> i7; CASE(9); i=> i8; CASE(10);i=> i9 861 INTEGER :: ncol, iv 862 LOGICAL :: pre(9) 863 !------------------------------------------------------------------------------------------------------------------------------ 864 pre(:) = [PRESENT(i1),PRESENT(i2),PRESENT(i3),PRESENT(i4),PRESENT(i5),PRESENT(i6),PRESENT(i7),PRESENT(i8),PRESENT(i9)] 865 ncol = SIZE(pre) 866 ALLOCATE(out(ncol)) 867 out(1) = i0 868 DO iv = 2, ncol; IF(.NOT.pre(iv-1)) CYCLE 869 SELECT CASE(iv-1) 870 CASE(1); i=> i1; CASE(2); i=> i2; CASE(3); i=> i3; CASE(4); i=> i4; CASE(5); i=> i5 871 CASE(6); i=> i6; CASE(7); i=> i7; CASE(8); i=> i8; CASE(9); i=> i9 774 872 END SELECT 775 873 out(iv) = i 776 874 END DO 777 END FUNCTION horzcat_i1 778 !============================================================================================================================== 779 FUNCTION horzcat_im(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9) RESULT(out) 780 INTEGER, TARGET, DIMENSION(:), INTENT(IN) :: i0 781 INTEGER, OPTIONAL, TARGET, DIMENSION(:), INTENT(IN) :: i1, i2, i3, i4, i5, i6, i7, i8, i9 875 END FUNCTION horzcat_i00 876 !============================================================================================================================== 877 FUNCTION horzcat_i10(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9) RESULT(out) 878 IMPLICIT NONE 879 INTEGER, INTENT(IN) :: i0(:), i1 880 INTEGER, OPTIONAL, INTENT(IN) :: i2, i3, i4, i5, i6, i7, i8, i9 881 INTEGER, ALLOCATABLE :: out(:), tmp(:) 882 INTEGER :: nc 883 nc = SIZE(i0) 884 tmp = horzcat_i00(i0(nc), i1, i2, i3, i4, i5, i6, i7, i8, i9) 885 IF(nc == 1) out = tmp 886 IF(nc /= 1) out = [i0(1:nc-1), tmp] 887 END FUNCTION horzcat_i10 888 !============================================================================================================================== 889 FUNCTION horzcat_i11(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9) RESULT(out) 890 IMPLICIT NONE 891 INTEGER, INTENT(IN) :: i0(:) 892 INTEGER, OPTIONAL, TARGET, INTENT(IN) :: i1(:), i2(:), i3(:), i4(:), i5(:), i6(:), i7(:), i8(:), i9(:) 782 893 INTEGER, ALLOCATABLE :: out(:,:) 783 !------------------------------------------------------------------------------------------------------------------------------784 894 INTEGER, POINTER :: i(:) 785 LOGICAL :: lv(10) 786 INTEGER :: nrow, ncol, iv, n 787 lv = [ .TRUE. , PRESENT(i1), PRESENT(i2), PRESENT(i3), PRESENT(i4) , & 788 PRESENT(i5), PRESENT(i6), PRESENT(i7), PRESENT(i8), PRESENT(i9) ] 789 nrow = SIZE(i0); ncol=COUNT(lv) 895 INTEGER :: nrow, ncol, iv, n 896 LOGICAL :: pre(9) 897 !------------------------------------------------------------------------------------------------------------------------------ 898 pre(:) = [PRESENT(i1),PRESENT(i2),PRESENT(i3),PRESENT(i4),PRESENT(i5),PRESENT(i6),PRESENT(i7),PRESENT(i8),PRESENT(i9)] 899 nrow = SIZE(i0) 900 ncol = 1+COUNT(pre) 790 901 ALLOCATE(out(nrow, ncol)) 791 DO iv=1, ncol 792 SELECT CASE(iv) 793 CASE(1); i=> i0; CASE(2); i=> i1; CASE(3); i=> i2; CASE(4); i=> i3; CASE(5); i=> i4 794 CASE(6); i=> i5; CASE(7); i=> i6; CASE(8); i=> i7; CASE(9); i=> i8; CASE(10);i=> i9 902 out(:,1) = i0 903 DO iv = 2, ncol; IF(.NOT.pre(iv-1)) CYCLE 904 SELECT CASE(iv-1) 905 CASE(1); i=> i1; CASE(2); i=> i2; CASE(3); i=> i3; CASE(4); i=> i4; CASE(5); i=> i5 906 CASE(6); i=> i6; CASE(7); i=> i7; CASE(8); i=> i8; CASE(9); i=> i9 795 907 END SELECT 796 908 n = SIZE(i, DIM=1) 797 IF(n /=nrow) THEN; CALL msg("Can't concatenate vectors of differing lengths"); STOP; END IF909 IF(n /= nrow) THEN; CALL msg("Can't concatenate vectors of differing lengths"); STOP; END IF 798 910 out(:,iv) = i(:) 799 911 END DO 800 END FUNCTION horzcat_im 801 !============================================================================================================================== 802 FUNCTION horzcat_r1(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9) RESULT(out) 803 REAL, TARGET, INTENT(IN) :: r0 912 END FUNCTION horzcat_i11 913 !============================================================================================================================== 914 FUNCTION horzcat_i21(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9) RESULT(out) 915 IMPLICIT NONE 916 INTEGER, INTENT(IN) :: i0(:,:), i1(:) 917 INTEGER, OPTIONAL, INTENT(IN) :: i2(:), i3(:), i4(:), i5(:), i6(:), i7(:), i8(:), i9(:) 918 INTEGER, ALLOCATABLE :: out(:,:), tmp(:,:) 919 INTEGER :: nc 920 nc = SIZE(i0, 2) 921 tmp = horzcat_i11(i0(:,nc), i1, i2, i3, i4, i5, i6, i7, i8, i9) 922 IF(nc == 1) out = tmp 923 IF(nc /= 1) out = RESHAPE([PACK(i0(:,1:nc-1), .TRUE.), PACK(tmp, .TRUE.)], SHAPE=[SIZE(i0, 1), nc + SIZE(tmp, 2)-1]) 924 END FUNCTION horzcat_i21 925 !============================================================================================================================== 926 FUNCTION horzcat_r00(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9) RESULT(out) 927 IMPLICIT NONE 928 REAL, INTENT(IN) :: r0 804 929 REAL, OPTIONAL, TARGET, INTENT(IN) :: r1, r2, r3, r4, r5, r6, r7, r8, r9 805 930 REAL, ALLOCATABLE :: out(:) 806 !------------------------------------------------------------------------------------------------------------------------------807 931 REAL, POINTER :: r 808 LOGICAL :: lv(10) 809 INTEGER :: iv 810 lv = [ .TRUE. , PRESENT(r1), PRESENT(r2), PRESENT(r3), PRESENT(r4) , & 811 PRESENT(r5), PRESENT(r6), PRESENT(r7), PRESENT(r8), PRESENT(r9) ] 812 ALLOCATE(out(COUNT(lv))) 813 DO iv=1, COUNT(lv) 814 SELECT CASE(iv) 815 CASE(1); r=> r0; CASE(2); r=> r1; CASE(3); r=> r2; CASE(4); r=> r3; CASE(5); r=> r4 816 CASE(6); r=> r5; CASE(7); r=> r6; CASE(8); r=> r7; CASE(9); r=> r8; CASE(10);r=> r9 932 INTEGER :: ncol, iv 933 LOGICAL :: pre(9) 934 !------------------------------------------------------------------------------------------------------------------------------ 935 pre(:) = [PRESENT(r1),PRESENT(r2),PRESENT(r3),PRESENT(r4),PRESENT(r5),PRESENT(r6),PRESENT(r7),PRESENT(r8),PRESENT(r9)] 936 ncol = 1+COUNT(pre) 937 ALLOCATE(out(ncol)) 938 out(1) = r0 939 DO iv = 2, ncol; IF(.NOT.pre(iv-1)) CYCLE 940 SELECT CASE(iv-1) 941 CASE(1); r=> r1; CASE(2); r=> r2; CASE(3); r=> r3; CASE(4); r=> r4; CASE(5); r=> r5 942 CASE(6); r=> r6; CASE(7); r=> r7; CASE(8); r=> r8; CASE(9); r=> r9 817 943 END SELECT 818 944 out(iv) = r 819 945 END DO 820 END FUNCTION horzcat_r1 821 !============================================================================================================================== 822 FUNCTION horzcat_rm(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9) RESULT(out) 823 REAL, TARGET, DIMENSION(:), INTENT(IN) :: r0 824 REAL, OPTIONAL, TARGET, DIMENSION(:), INTENT(IN) :: r1, r2, r3, r4, r5, r6, r7, r8, r9 946 END FUNCTION horzcat_r00 947 !============================================================================================================================== 948 FUNCTION horzcat_r10(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9) RESULT(out) 949 IMPLICIT NONE 950 REAL, INTENT(IN) :: r0(:), r1 951 REAL, OPTIONAL, INTENT(IN) :: r2, r3, r4, r5, r6, r7, r8, r9 952 REAL, ALLOCATABLE :: out(:), tmp(:) 953 INTEGER :: nc 954 nc = SIZE(r0) 955 tmp = horzcat_r00(r0(nc), r1, r2, r3, r4, r5, r6, r7, r8, r9) 956 IF(nc == 1) out = tmp 957 IF(nc /= 1) out = [r0(1:nc-1), tmp] 958 END FUNCTION horzcat_r10 959 !============================================================================================================================== 960 FUNCTION horzcat_r11(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9) RESULT(out) 961 IMPLICIT NONE 962 REAL, INTENT(IN) :: r0(:) 963 REAL, OPTIONAL, TARGET, INTENT(IN) :: r1(:), r2(:), r3(:), r4(:), r5(:), r6(:), r7(:), r8(:), r9(:) 825 964 REAL, ALLOCATABLE :: out(:,:) 826 !------------------------------------------------------------------------------------------------------------------------------827 965 REAL, POINTER :: r(:) 828 LOGICAL :: lv(10) 829 INTEGER :: nrow, ncol, iv, n 830 lv = [ .TRUE. , PRESENT(r1), PRESENT(r2), PRESENT(r3), PRESENT(r4) , & 831 PRESENT(r5), PRESENT(r6), PRESENT(r7), PRESENT(r8), PRESENT(r9) ] 832 nrow = SIZE(r0); ncol=COUNT(lv) 966 INTEGER :: nrow, ncol, iv, n 967 LOGICAL :: pre(9) 968 !------------------------------------------------------------------------------------------------------------------------------ 969 pre(:) = [PRESENT(r1),PRESENT(r2),PRESENT(r3),PRESENT(r4),PRESENT(r5),PRESENT(r6),PRESENT(r7),PRESENT(r8),PRESENT(r9)] 970 nrow = SIZE(r0) 971 ncol = 1+COUNT(pre) 833 972 ALLOCATE(out(nrow, ncol)) 834 DO iv=1, ncol 835 SELECT CASE(iv) 836 CASE(1); r=> r0; CASE(2); r=> r1; CASE(3); r=> r2; CASE(4); r=> r3; CASE(5); r=> r4 837 CASE(6); r=> r5; CASE(7); r=> r6; CASE(8); r=> r7; CASE(9); r=> r8; CASE(10);r=> r9 973 out(:,1) = r0 974 DO iv = 2, ncol; IF(.NOT.pre(iv-1)) CYCLE 975 SELECT CASE(iv-1) 976 CASE(1); r=> r1; CASE(2); r=> r2; CASE(3); r=> r3; CASE(4); r=> r4; CASE(5); r=> r5 977 CASE(6); r=> r5; CASE(7); r=> r7; CASE(8); r=> r8; CASE(9); r=> r9 838 978 END SELECT 839 979 n = SIZE(r, DIM=1) 840 IF(n /=nrow) THEN; CALL msg("Can't concatenate vectors of differing lengths"); STOP; END IF980 IF(n /= nrow) THEN; CALL msg("Can't concatenate vectors of differing lengths"); STOP; END IF 841 981 out(:,iv) = r(:) 842 982 END DO 843 END FUNCTION horzcat_rm 844 !============================================================================================================================== 845 FUNCTION horzcat_d1(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9) RESULT(out) 846 DOUBLE PRECISION, TARGET, INTENT(IN) :: d0 983 END FUNCTION horzcat_r11 984 !============================================================================================================================== 985 FUNCTION horzcat_r21(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9) RESULT(out) 986 IMPLICIT NONE 987 REAL, INTENT(IN) :: r0(:,:), r1(:) 988 REAL, OPTIONAL, INTENT(IN) :: r2(:), r3(:), r4(:), r5(:), r6(:), r7(:), r8(:), r9(:) 989 REAL, ALLOCATABLE :: out(:,:), tmp(:,:) 990 INTEGER :: nc 991 nc = SIZE(r0, 2) 992 tmp = horzcat_r11(r0(:,nc), r1, r2, r3, r4, r5, r6, r7, r8, r9) 993 IF(nc == 1) out = tmp 994 IF(nc /= 1) out = RESHAPE([PACK(r0(:,1:nc-1), .TRUE.), PACK(tmp, .TRUE.)], SHAPE=[SIZE(r0, 1), nc + SIZE(tmp, 2)-1]) 995 END FUNCTION horzcat_r21 996 !============================================================================================================================== 997 FUNCTION horzcat_d00(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9) RESULT(out) 998 IMPLICIT NONE 999 DOUBLE PRECISION, INTENT(IN) :: d0 847 1000 DOUBLE PRECISION, OPTIONAL, TARGET, INTENT(IN) :: d1, d2, d3, d4, d5, d6, d7, d8, d9 848 1001 DOUBLE PRECISION, ALLOCATABLE :: out(:) 849 !------------------------------------------------------------------------------------------------------------------------------850 1002 DOUBLE PRECISION, POINTER :: d 851 LOGICAL :: lv(10) 852 INTEGER :: iv 853 lv = [ .TRUE. , PRESENT(d1), PRESENT(d2), PRESENT(d3), PRESENT(d4) , & 854 PRESENT(d5), PRESENT(d6), PRESENT(d7), PRESENT(d8), PRESENT(d9) ] 855 ALLOCATE(out(COUNT(lv))) 856 DO iv=1, COUNT(lv) 857 SELECT CASE(iv) 858 CASE(1); d=> d0; CASE(2); d=> d1; CASE(3); d=> d2; CASE(4); d=> d3; CASE(5); d=> d4 859 CASE(6); d=> d5; CASE(7); d=> d6; CASE(8); d=> d7; CASE(9); d=> d8; CASE(10);d=> d9 1003 INTEGER :: ncol, iv 1004 LOGICAL :: pre(9) 1005 !------------------------------------------------------------------------------------------------------------------------------ 1006 pre(:) = [PRESENT(d1),PRESENT(d2),PRESENT(d3),PRESENT(d4),PRESENT(d5),PRESENT(d6),PRESENT(d7),PRESENT(d8),PRESENT(d9)] 1007 ncol = 1+COUNT(pre) 1008 ALLOCATE(out(ncol)) 1009 out(1) = d0 1010 DO iv = 2, ncol; IF(.NOT.pre(iv-1)) CYCLE 1011 SELECT CASE(iv-1) 1012 CASE(1); d=> d1; CASE(2); d=> d2; CASE(3); d=> d3; CASE(4); d=> d4; CASE(5); d=> d5 1013 CASE(6); d=> d6; CASE(7); d=> d7; CASE(8); d=> d8; CASE(9); d=> d9 860 1014 END SELECT 861 1015 out(iv) = d 862 1016 END DO 863 END FUNCTION horzcat_d1 864 !============================================================================================================================== 865 FUNCTION horzcat_dm(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9) RESULT(out) 866 DOUBLE PRECISION, TARGET, DIMENSION(:), INTENT(IN) :: d0 867 DOUBLE PRECISION, OPTIONAL, TARGET, DIMENSION(:), INTENT(IN) :: d1, d2, d3, d4, d5, d6, d7, d8, d9 1017 END FUNCTION horzcat_d00 1018 !============================================================================================================================== 1019 FUNCTION horzcat_d10(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9) RESULT(out) 1020 IMPLICIT NONE 1021 DOUBLE PRECISION, INTENT(IN) :: d0(:), d1 1022 DOUBLE PRECISION, OPTIONAL, INTENT(IN) :: d2, d3, d4, d5, d6, d7, d8, d9 1023 DOUBLE PRECISION, ALLOCATABLE :: out(:), tmp(:) 1024 INTEGER :: nc 1025 nc = SIZE(d0) 1026 tmp = horzcat_d00(d0(nc), d1, d2, d3, d4, d5, d6, d7, d8, d9) 1027 IF(nc == 1) out = tmp 1028 IF(nc /= 1) out = [d0(1:nc-1), tmp] 1029 END FUNCTION horzcat_d10 1030 !============================================================================================================================== 1031 FUNCTION horzcat_d11(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9) RESULT(out) 1032 IMPLICIT NONE 1033 DOUBLE PRECISION, INTENT(IN) :: d0(:) 1034 DOUBLE PRECISION, OPTIONAL, TARGET, INTENT(IN) :: d1(:), d2(:), d3(:), d4(:), d5(:), d6(:), d7(:), d8(:), d9(:) 868 1035 DOUBLE PRECISION, ALLOCATABLE :: out(:,:) 869 !------------------------------------------------------------------------------------------------------------------------------870 1036 DOUBLE PRECISION, POINTER :: d(:) 871 LOGICAL :: lv(10) 872 INTEGER :: nrow, ncol, iv, n 873 lv = [ .TRUE. , PRESENT(d1), PRESENT(d2), PRESENT(d3), PRESENT(d4) , & 874 PRESENT(d5), PRESENT(d6), PRESENT(d7), PRESENT(d8), PRESENT(d9) ] 875 nrow = SIZE(d0); ncol=COUNT(lv) 1037 INTEGER :: nrow, ncol, iv, n 1038 LOGICAL :: pre(9) 1039 !------------------------------------------------------------------------------------------------------------------------------ 1040 nrow = SIZE(d0) 1041 pre(:) = [PRESENT(d1),PRESENT(d2),PRESENT(d3),PRESENT(d4),PRESENT(d5),PRESENT(d6),PRESENT(d7),PRESENT(d8),PRESENT(d9)] 1042 ncol = 1+COUNT(pre) 876 1043 ALLOCATE(out(nrow, ncol)) 877 DO iv =1, ncol878 SELECT CASE(iv )879 CASE(1); d=> d 0; CASE(2); d=> d1; CASE(3); d=> d2; CASE(4); d=> d3; CASE(5); d=> d4880 CASE(6); d=> d 5; CASE(7); d=> d6; CASE(8); d=> d7; CASE(9); d=> d8; CASE(10);d=> d91044 DO iv = 2, ncol; IF(.NOT.pre(iv-1)) CYCLE 1045 SELECT CASE(iv-1) 1046 CASE(1); d=> d1; CASE(2); d=> d2; CASE(3); d=> d3; CASE(4); d=> d4; CASE(5); d=> d5 1047 CASE(6); d=> d6; CASE(7); d=> d7; CASE(8); d=> d8; CASE(9); d=> d9 881 1048 END SELECT 882 1049 n = SIZE(d, DIM=1) 883 IF(n /=nrow) THEN; CALL msg("Can't concatenate vectors of differing lengths"); STOP; END IF1050 IF(n /= nrow) THEN; CALL msg("Can't concatenate vectors of differing lengths"); STOP; END IF 884 1051 out(:,iv) = d(:) 885 1052 END DO 886 END FUNCTION horzcat_dm 1053 END FUNCTION horzcat_d11 1054 !============================================================================================================================== 1055 FUNCTION horzcat_d21(d0, d1, d2, d3, d4, d5, d6, d7, d8, d9) RESULT(out) 1056 IMPLICIT NONE 1057 DOUBLE PRECISION, INTENT(IN) :: d0(:,:), d1(:) 1058 DOUBLE PRECISION, OPTIONAL, INTENT(IN) :: d2(:), d3(:), d4(:), d5(:), d6(:), d7(:), d8(:), d9(:) 1059 DOUBLE PRECISION, ALLOCATABLE :: out(:,:), tmp(:,:) 1060 INTEGER :: nc 1061 nc = SIZE(d0, 2) 1062 tmp = horzcat_d11(d0(:,nc), d1, d2, d3, d4, d5, d6, d7, d8, d9) 1063 IF(nc == 1) out = tmp 1064 IF(nc /= 1) out = RESHAPE([PACK(d0(:,1:nc-1), .TRUE.), PACK(tmp, .TRUE.)], SHAPE=[SIZE(d0, 1), nc + SIZE(tmp, 2)-1]) 1065 END FUNCTION horzcat_d21 887 1066 !============================================================================================================================== 888 1067 … … 896 1075 !============================================================================================================================== 897 1076 LOGICAL FUNCTION dispTable(p, titles, s, i, r, rFmt, nRowMax, nColMax, nHead, unit, sub) RESULT(lerr) 1077 IMPLICIT NONE 898 1078 CHARACTER(LEN=*), INTENT(IN) :: p !--- DISPLAY MAP: s/i/r 899 1079 CHARACTER(LEN=*), INTENT(IN) :: titles(:) !--- TITLES (ONE EACH COLUMN) … … 1004 1184 !============================================================================================================================== 1005 1185 LOGICAL FUNCTION dispNamelist(unt, p, titles, s, i, r, rFmt, llast) RESULT(lerr) 1186 IMPLICIT NONE 1006 1187 INTEGER, INTENT(IN) :: unt !--- Output unit 1007 1188 CHARACTER(LEN=*), INTENT(IN) :: p !--- DISPLAY MAP: s/i/r … … 1086 1267 !============================================================================================================================== 1087 1268 LOGICAL FUNCTION dispOutliers_1(ll, a, n, err_msg, nam, subn, nRowmax, nColMax, nHead, unit) RESULT(lerr) 1269 IMPLICIT NONE 1088 1270 ! Display outliers list in tables 1089 1271 ! If "nam" is supplied, it means the last index is for tracers => one table each tracer for rank > 2. … … 1115 1297 1116 1298 rk = SIZE(n); nv = SIZE(vnm) 1117 IF(test(fmsg('SIZE(nam) /= 1 and /= last "n" element', sub, nv /= 1 .AND. nv /= n(rk), unt),lerr)) RETURN1118 IF(test(fmsg('ll" and "a" sizes mismatch', sub, SIZE(a) /= SIZE(ll), unt),lerr)) RETURN1119 IF(test(fmsg('profile "n" does not match "a" and "ll', sub, SIZE(a) /= PRODUCT(n), unt),lerr)) RETURN1299 lerr = nv/=1 .AND. nv/=n(rk); CALL msg('SIZE(nam) /= 1 and /= last "n" element', sub, lerr); IF(lerr) RETURN 1300 lerr = SIZE(a) /= SIZE(ll); CALL msg('ll" and "a" sizes mismatch', sub, lerr); IF(lerr) RETURN 1301 lerr = SIZE(a) /= PRODUCT(n); CALL msg('profile "n" does not match "a" and "ll', sub, lerr); IF(lerr) RETURN 1120 1302 CALL msg(mes, sub, unit=unt) 1121 1303 … … 1164 1346 !============================================================================================================================== 1165 1347 LOGICAL FUNCTION dispOutliers_2(ll, a, n, err_msg, nam, subn, nRowMax, nColMax, nHead, unit) RESULT(lerr) 1348 IMPLICIT NONE 1166 1349 ! Display outliers list in tables 1167 1350 ! If "nam" is supplied and, it means the last index is for tracers => one table each tracer for rank > 2. … … 1221 1404 !============================================================================================================================== 1222 1405 LOGICAL FUNCTION reduceExpr_1(str, val) RESULT(lerr) 1406 IMPLICIT NONE 1223 1407 CHARACTER(LEN=*), INTENT(IN) :: str 1224 1408 CHARACTER(LEN=maxlen), INTENT(OUT) :: val … … 1254 1438 DO WHILE(nl > 1) 1255 1439 i = 1; DO WHILE(ip(i) /= 1 .OR. ip(i+1) /= 2); i = i + 1; END DO !IF(i > SIZE(ip)+1) EXIT;END DO 1256 IF(test(reduceExpr_basic(vl(i+1), v), lerr)) RETURN1440 lerr = reduceExpr_basic(vl(i+1), v); IF(lerr) RETURN 1257 1441 v = TRIM(vl(i))//TRIM(v); IF(i+2<=nl) v=TRIM(v)//TRIM(vl(i+2)) 1258 1442 vv = v//REPEAT(' ',768) … … 1270 1454 !============================================================================================================================== 1271 1455 LOGICAL FUNCTION reduceExpr_basic(str, val) RESULT(lerr) 1456 IMPLICIT NONE 1272 1457 CHARACTER(LEN=*), INTENT(IN) :: str 1273 1458 CHARACTER(LEN=*), INTENT(OUT) :: val … … 1284 1469 op = ['^','/','*','+','-'] !--- List of recognized operations 1285 1470 s = str 1286 IF(test(strParse_m(s, op, ky, lSc=.TRUE., id = id), lerr)) RETURN !--- Parse the values 1471 lerr = strParse_m(s, op, ky, lSc=.TRUE., id = id) !--- Parse the values 1472 IF(lerr) RETURN !--- Problem with the parsing 1287 1473 vl = str2dble(ky) !--- Conversion to doubles 1288 1474 lerr = ANY(vl >= HUGE(1.d0)) 1289 IF(fmsg('Some values are non-numeric in: '//TRIM(s), ll=lerr)) RETURN !--- Non-numerical values found 1475 CALL msg('Some values are non-numeric in: '//TRIM(s), ll=lerr) 1476 IF(lerr) RETURN !--- Non-numerical values found 1290 1477 DO io = 1, SIZE(op) !--- Loop on known operators (order matters !) 1291 1478 DO i = SIZE(id), 1, -1 !--- Loop on found operators … … 1293 1480 IF(id(i) /= io) CYCLE !--- Current found operator is not op(io) 1294 1481 vm = vl(i); vp = vl(i+1) !--- Couple of values used for current operation 1295 SELECT CASE(op(io)) 1482 SELECT CASE(op(io)) !--- Perform operation on the two values 1296 1483 CASE('^'); v = vm**vp 1297 1484 CASE('/'); v = vm/vp … … 1311 1498 !============================================================================================================================== 1312 1499 FUNCTION reduceExpr_m(str, val) RESULT(lerr) 1500 IMPLICIT NONE 1313 1501 LOGICAL, ALLOCATABLE :: lerr(:) 1314 1502 CHARACTER(LEN=*), INTENT(IN) :: str(:) … … 1326 1514 !============================================================================================================================== 1327 1515 ELEMENTAL LOGICAL FUNCTION is_numeric(str) RESULT(out) 1516 IMPLICIT NONE 1328 1517 CHARACTER(LEN=*), INTENT(IN) :: str 1329 1518 REAL :: x … … 1341 1530 !=== Convert a string into a logical/integer integer or an integer/real into a string ========================================= 1342 1531 !============================================================================================================================== 1343 ELEMENTAL LOGICAL FUNCTION str2bool(str) RESULT(out) 1532 ELEMENTAL INTEGER FUNCTION str2bool(str) RESULT(out) !--- Result: 0/1 for .FALSE./.TRUE., -1 if not a valid boolean 1533 IMPLICIT NONE 1344 1534 CHARACTER(LEN=*), INTENT(IN) :: str 1345 1535 INTEGER :: ierr 1346 READ(str,*,IOSTAT=ierr) out 1347 IF(ierr==0) RETURN 1348 out = ANY(['t ','true ','.true.','y ','yes ']==strLower(str)) 1536 LOGICAL :: lout 1537 READ(str,*,IOSTAT=ierr) lout 1538 out = -HUGE(1) 1539 IF(ierr /= 0) THEN 1540 IF(ANY(['.false.', 'false ', 'no ', 'f ', 'n '] == strLower(str))) out = 0 1541 IF(ANY(['.true. ', 'true ', 'yes ', 't ', 'y '] == strLower(str))) out = 1 1542 ELSE 1543 out = 0; IF(lout) out = 1 1544 END IF 1349 1545 END FUNCTION str2bool 1350 1546 !============================================================================================================================== 1351 1547 ELEMENTAL INTEGER FUNCTION str2int(str) RESULT(out) 1548 IMPLICIT NONE 1352 1549 CHARACTER(LEN=*), INTENT(IN) :: str 1353 1550 INTEGER :: ierr … … 1357 1554 !============================================================================================================================== 1358 1555 ELEMENTAL REAL FUNCTION str2real(str) RESULT(out) 1556 IMPLICIT NONE 1359 1557 CHARACTER(LEN=*), INTENT(IN) :: str 1360 1558 INTEGER :: ierr … … 1364 1562 !============================================================================================================================== 1365 1563 ELEMENTAL DOUBLE PRECISION FUNCTION str2dble(str) RESULT(out) 1564 IMPLICIT NONE 1366 1565 CHARACTER(LEN=*), INTENT(IN) :: str 1367 1566 INTEGER :: ierr … … 1371 1570 !============================================================================================================================== 1372 1571 ELEMENTAL CHARACTER(LEN=maxlen) FUNCTION bool2str(b) RESULT(out) 1572 IMPLICIT NONE 1373 1573 LOGICAL, INTENT(IN) :: b 1374 1574 WRITE(out,*)b … … 1377 1577 !============================================================================================================================== 1378 1578 ELEMENTAL CHARACTER(LEN=maxlen) FUNCTION int2str(i, nDigits) RESULT(out) 1579 IMPLICIT NONE 1379 1580 INTEGER, INTENT(IN) :: i 1380 1581 INTEGER, OPTIONAL, INTENT(IN) :: nDigits … … 1387 1588 !============================================================================================================================== 1388 1589 ELEMENTAL CHARACTER(LEN=maxlen) FUNCTION real2str(r,fmt) RESULT(out) 1590 IMPLICIT NONE 1389 1591 REAL, INTENT(IN) :: r 1390 1592 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: fmt … … 1396 1598 !============================================================================================================================== 1397 1599 ELEMENTAL CHARACTER(LEN=maxlen) FUNCTION dble2str(d,fmt) RESULT(out) 1600 IMPLICIT NONE 1398 1601 DOUBLE PRECISION, INTENT(IN) :: d 1399 1602 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: fmt … … 1405 1608 !============================================================================================================================== 1406 1609 ELEMENTAL SUBROUTINE cleanZeros(s) 1610 IMPLICIT NONE 1407 1611 CHARACTER(LEN=*), INTENT(INOUT) :: s 1408 1612 INTEGER :: ls, ix, i … … 1422 1626 !============================================================================================================================== 1423 1627 FUNCTION addQuotes_1(s) RESULT(out) 1628 IMPLICIT NONE 1424 1629 CHARACTER(LEN=*), INTENT(IN) :: s 1425 1630 CHARACTER(LEN=:), ALLOCATABLE :: out … … 1428 1633 !============================================================================================================================== 1429 1634 FUNCTION addQuotes_m(s) RESULT(out) 1635 IMPLICIT NONE 1430 1636 CHARACTER(LEN=*), INTENT(IN) :: s(:) 1431 1637 CHARACTER(LEN=:), ALLOCATABLE :: out(:) … … 1440 1646 !============================================================================================================================== 1441 1647 ELEMENTAL LOGICAL FUNCTION needQuotes(s) RESULT(out) 1648 IMPLICIT NONE 1442 1649 CHARACTER(LEN=*), INTENT(IN) :: s 1443 1650 CHARACTER(LEN=1) :: b, e … … 1454 1661 !============================================================================================================================== 1455 1662 LOGICAL FUNCTION checkList(str, lerr, message, items, reason, nmax) RESULT(out) 1663 IMPLICIT NONE 1456 1664 ! Purpose: Messages in case a list contains wrong elements (indicated by lerr boolean vector). 1457 1665 ! Note: Return value "out" is .TRUE. if there are errors (ie at least one element of "lerr" is TRUE). … … 1476 1684 !============================================================================================================================== 1477 1685 SUBROUTINE removeComment(str) 1686 IMPLICIT NONE 1478 1687 CHARACTER(LEN=*), INTENT(INOUT) :: str 1479 1688 INTEGER :: ix
Note: See TracChangeset
for help on using the changeset viewer.