Changeset 2
- Timestamp:
- Dec 8, 2021, 9:25:11 PM (3 years ago)
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
readTracFiles_mod.f90
r1 r2 1 1 MODULE readTracFiles_mod 2 2 3 USE strings_mod, ONLY: msg, testFile, strFind, strStack, strReduce, strHead, strCount, find, dispTable, fmsg, &4 removeComment, cat, checkList, strIdx, strParse, strReplace, strTail, reduceExpr, test, modname, get_in5 USE trac_types_mod, ONLY : tra , iso, db, kys3 USE strings_mod, ONLY: msg, testFile, strFind, strStack, strReduce, strHead, strCount, find, maxlen, fmsg, & 4 removeComment, cat, checkList, strIdx, strParse, strReplace, strTail, reduceExpr, test, get_in, dispTable 5 USE trac_types_mod, ONLY : trac_type, isot_type, keys_type 6 6 7 7 IMPLICIT NONE … … 10 10 11 11 PUBLIC :: initIsotopes 12 PUBLIC :: readTracersFiles, aliasTracer, tracersSubset, indexUpdate 13 PUBLIC :: readIsotopesFile 14 PUBLIC :: getKey_init, getKey, setDirectKeys !--- FUNCTIONS TO GET KEYS FROMtracers & isotopes15 16 PUBLIC :: known_phases, old_phases, nphases, phases_names, phases_sep, &!--- VARIABLES RELATED TO THE PHASES17 delPhase, addPhase !---ROUTINES TO ADD/REMOVE PHASE TO/FROM A NAME18 19 PUBLIC :: tran0, idxAncestor, ancestor !--- GEN 0 TRACER + TOOLS FOR GENERATIONS20 21 !------------------------------------------------------------------------------------------------------------------------------ 22 TYPE db!=== TYPE FOR TRACERS SECTION23 CHARACTER(LEN= 256):: name !--- Section name24 TYPE(tra ), ALLOCATABLE :: trac(:)!--- Tracers descriptors25 END TYPE d b12 PUBLIC :: readTracersFiles, aliasTracer, tracersSubset, indexUpdate!--- TOOLS ASSOCIATED TO TRACERS DESCRIPTORS 13 PUBLIC :: readIsotopesFile !--- TOOLS ASSOCIATED TO ISOTOPES DESCRIPTORS 14 PUBLIC :: getKey_init, getKey, setDirectKeys !--- GET/SET KEYS FROM/TO tracers & isotopes 15 16 PUBLIC :: known_phases, old_phases, nphases, phases_names, & !--- VARIABLES RELATED TO THE PHASES 17 phases_sep, delPhase, addPhase !--- + ROUTINES TO ADD/REMOVE PHASE TO/FROM A NAME 18 19 PUBLIC :: tran0, idxAncestor, ancestor !--- GENERATION 0 TRACER + TOOLS FOR GENERATIONS 20 21 !------------------------------------------------------------------------------------------------------------------------------ 22 TYPE :: dataBase_type !=== TYPE FOR TRACERS SECTION 23 CHARACTER(LEN=maxlen) :: name !--- Section name 24 TYPE(trac_type), ALLOCATABLE :: trac(:) !--- Tracers descriptors 25 END TYPE dataBase_type 26 26 !------------------------------------------------------------------------------------------------------------------------------ 27 27 INTERFACE getKey … … 29 29 END INTERFACE getKey 30 30 !------------------------------------------------------------------------------------------------------------------------------ 31 INTERFACE tracersSubset; MODULE PROCEDURE trSubset_Indx, trSubset_Name, trSubset_ Nam1; END INTERFACE tracersSubset31 INTERFACE tracersSubset; MODULE PROCEDURE trSubset_Indx, trSubset_Name, trSubset_gen0Name; END INTERFACE tracersSubset 32 32 INTERFACE idxAncestor; MODULE PROCEDURE idxAncestor_1, idxAncestor_m; END INTERFACE idxAncestor 33 33 INTERFACE ancestor; MODULE PROCEDURE ancestor_1, ancestor_m; END INTERFACE ancestor … … 36 36 37 37 !=== MAIN DATABASE: files sections descriptors 38 TYPE(d b), SAVE, ALLOCATABLE, TARGET :: dBase(:)38 TYPE(dataBase_type), SAVE, ALLOCATABLE, TARGET :: dBase(:) 39 39 40 40 !--- SOME PARAMETERS THAT ARE NOT LIKELY TO CHANGE OFTEN 41 CHARACTER(LEN= 256), SAVE :: tran0 = 'air'!--- Default transporting fluid42 CHARACTER(LEN= 256), PARAMETER :: old_phases = 'vli'!--- Old phases for water (no separator)43 CHARACTER(LEN= 256), PARAMETER :: known_phases = 'gls'!--- Known phases initials44 INTEGER, PARAMETER :: nphases = LEN_TRIM(known_phases)!--- Number of phases45 CHARACTER(LEN= 256), SAVE :: phases_names(nphases) &!--- Known phases names46 41 CHARACTER(LEN=maxlen), SAVE :: tran0 = 'air' !--- Default transporting fluid 42 CHARACTER(LEN=maxlen), PARAMETER :: old_phases = 'vli' !--- Old phases for water (no separator) 43 CHARACTER(LEN=maxlen), PARAMETER :: known_phases = 'gls' !--- Known phases initials 44 INTEGER, PARAMETER :: nphases=LEN_TRIM(known_phases) !--- Number of phases 45 CHARACTER(LEN=maxlen), SAVE :: phases_names(nphases) & !--- Known phases names 46 = ['gaseous', 'liquid ', 'solid '] 47 47 CHARACTER(LEN=1), SAVE :: phases_sep = '_' !--- Phase separator 48 48 LOGICAL, SAVE :: tracs_merge = .TRUE. !--- Merge/stack tracers lists … … 50 50 51 51 !=== LOCAL COPIES OF THE TRACERS AND ISOTOPES DESCRIPTORS, USED BY getKey (INITIALIZED IN getKey_init) 52 TYPE(tra), ALLOCATABLE, TARGET, SAVE :: tracers(:) 53 TYPE(iso), ALLOCATABLE, TARGET, SAVE :: isotopes(:) 54 52 TYPE(trac_type), ALLOCATABLE, TARGET, SAVE :: tracers(:) 53 TYPE(isot_type), ALLOCATABLE, TARGET, SAVE :: isotopes(:) 54 55 CHARACTER(LEN=maxlen) :: modname 55 56 56 57 CONTAINS … … 73 74 !=== FUNCTION RETURN VALUE "lerr" IS FALSE IN CASE SOMETHING WENT WRONG. 74 75 !=== ABOUT THE KEYS: 75 ! * The "keys" component (of type k ys) is in principle enough to store everything we could need.76 ! * The "keys" component (of type keys_type) is in principle enough to store everything we could need. 76 77 ! But some variables are stored as direct-access keys to make the code more readable and because they are used often. 77 78 ! * Most of the direct-access keys are set in this module, but some are not (lnam, iadv and itr for example). 78 79 ! * Some of the direct-access keys must be updated (using the routine "setDirectKeys") is a subset of "tracers(:)" 79 ! is extracted: the indexes are no longer valid for a subset (examples: tracers(:) iprnt or tracers(:)%ichld).80 ! is extracted: the indexes are no longer valid for a subset (examples: tracers(:)%iqParent or tracers(:)%ichld). 80 81 ! * If you need to convert a %key/%val pair into a direct-access key, add the corresponding line in "setDirectKeys". 81 82 !============================================================================================================================== 82 83 LOGICAL FUNCTION readTracersFiles(type_trac, fType, tracs) RESULT(lerr) 83 84 !------------------------------------------------------------------------------------------------------------------------------ 84 CHARACTER(LEN=*), INTENT(IN) :: type_trac!--- List of components used85 INTEGER, INTENT(OUT) :: fType!--- Type of input file found86 TYPE(tra ), ALLOCATABLE, INTENT(OUT) :: tracs(:)87 CHARACTER(LEN= 256),ALLOCATABLE :: s(:), sections(:), trac_files(:)88 CHARACTER(LEN= 256):: str, fname, mesg89 INTEGER :: is, nsec, ierr, it, ntrac, ns, ip90 LOGICAL, ALLOCATABLE :: ll(:), lGen3(:)85 CHARACTER(LEN=*), INTENT(IN) :: type_trac !--- List of components used 86 INTEGER, INTENT(OUT) :: fType !--- Type of input file found 87 TYPE(trac_type), ALLOCATABLE, INTENT(OUT) :: tracs(:) 88 CHARACTER(LEN=maxlen), ALLOCATABLE :: s(:), sections(:), trac_files(:) 89 CHARACTER(LEN=maxlen) :: str, fname, mesg 90 INTEGER :: is, nsec, ierr, it, ntrac, ns, ip 91 LOGICAL, ALLOCATABLE :: ll(:), lGen3(:) 91 92 !------------------------------------------------------------------------------------------------------------------------------ 92 93 lerr = .FALSE. 93 !modname = 'readTracersFiles'94 modname = 'readTracersFiles' 94 95 IF(.NOT.ALLOCATED(dBase)) ALLOCATE(dBase(0)) 95 96 … … 111 112 112 113 !--- TELLS WHAT WAS IS ABOUT TO BE USED 113 IF ( fmsg(fType==0, 'No adequate tracers description file(s) found ; default values will be used')) RETURN114 CALL msg( fType==1, 'Trying to read old-style tracers description file "traceur.def"')115 CALL msg( fType==2, 'Trying to read the new style multi-sections tracers description file "tracer.def"')116 CALL msg( fType==3, 'Trying to read the new style single section tracers description files "tracer_*.def"')114 IF (fmsg('No adequate tracers description file(s) found ; default values will be used', modname, fType==0)) RETURN 115 CALL msg('Trying to read old-style tracers description file "traceur.def"', modname, fType==1) 116 CALL msg('Trying to read the new style multi-sections tracers description file "tracer.def"', modname, fType==2) 117 CALL msg('Trying to read the new style single section tracers description files "tracer_*.def"', modname, fType==3) 117 118 118 119 !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ … … 124 125 !--- GET THE TRACERS NUMBER 125 126 READ(90,'(i3)',IOSTAT=ierr)ntrac !--- Number of lines/tracers 126 IF(test(fmsg( ierr /= 0, 'Invalid format for "'//TRIM(fname)//'"'), lerr)) RETURN127 IF(test(fmsg('Invalid format for "'//TRIM(fname)//'"', modname, ierr /= 0), lerr)) RETURN 127 128 128 129 !--- READ THE REMAINING LINES: <hadv> <vadv> <tracer> [<transporting fluid>] … … 130 131 DO it=1,ntrac !=== READ RAW DATA: loop on the line/tracer number 131 132 READ(90,'(a)',IOSTAT=ierr) str 132 IF(test(fmsg( ierr>0, 'Invalid format for "' //TRIM(fname)//'"'), lerr)) RETURN133 IF(test(fmsg( ierr<0, 'Not enough lines in "'//TRIM(fname)//'"'), lerr)) RETURN133 IF(test(fmsg('Invalid format for "' //TRIM(fname)//'"', modname, ierr>0), lerr)) RETURN 134 IF(test(fmsg('Not enough lines in "'//TRIM(fname)//'"', modname, ierr<0), lerr)) RETURN 134 135 ll = strParse(str, ' ', s, n=ns) 135 136 tracs(it)%keys%key = ['hadv', 'vadv'] 136 137 tracs(it)%keys%val = s(1:2) 137 CALL msg( ns == 3 .AND. it == 1, 'This file is for air tracers only')138 CALL msg( ns == 4 .AND. it == 1, 'This files specifies the transporting fluid')139 tracs(it)%name = s(3); tracs(it)%phas = known_phases(1:1)!--- Default: name, gazeous phase "g"138 CALL msg('This file is for air tracers only', modname, ns == 3 .AND. it == 1) 139 CALL msg('This files specifies the transporting fluid', modname, ns == 4 .AND. it == 1) 140 tracs(it)%name = s(3); tracs(it)%phase = known_phases(1:1) !--- Default: name, gazeous phase "g" 140 141 DO ip = 1, nphases !--- Deal with old water names 141 142 IF(s(3) /= 'H2O'//old_phases(ip:ip)) CYCLE 142 tracs(it)%phas = known_phases(ip:ip); tracs(it)%name = 'H2O'//phases_sep//TRIM(tracs(it)%phas)143 tracs(it)%phase = known_phases(ip:ip); tracs(it)%name = 'H2O'//phases_sep//TRIM(tracs(it)%phase) 143 144 END DO 144 tracs(it)%p rnt = tran0!--- Default transporting fluid: Air145 IF(ns == 4) tracs(it)%p rnt = s(4)!--- Transporting fluid name145 tracs(it)%parent = tran0 !--- Default transporting fluid: Air 146 IF(ns == 4) tracs(it)%parent = s(4) !--- Transporting fluid name 146 147 END DO 147 148 CLOSE(90) 148 149 149 lGen3 = tracs%i gen==3150 CALL setGeneration(tracs) !--- Determine tracs(:)%i gen values150 lGen3 = tracs%iGeneration==3 151 CALL setGeneration(tracs) !--- Determine tracs(:)%iGeneration values 151 152 IF(test(checkTracers(tracs, fname,fname),lerr)) RETURN !--- Detect orphans and check phases 152 153 IF(test(checkUnique (tracs,lGen3,fname,fname),lerr)) RETURN !--- Detect repeated tracers … … 160 161 161 162 !=== USING NEW FORMAT TRACERS DESCRIPTION FILES WITH POSSIBLY SEVERAL SECTIONS 162 CALL msg( nsec > 1 .AND. tracs_merge, 'The multiple required sections will be MERGED.')163 CALL msg( nsec > 1 .AND. .NOT.tracs_merge, 'The multiple required sections will be CUMULATED.')163 CALL msg('The multiple required sections will be MERGED.', modname, nsec > 1 .AND. tracs_merge) 164 CALL msg('The multiple required sections will be CUMULATED.', modname, nsec > 1 .AND. .NOT.tracs_merge) 164 165 165 166 !=== FEED THE DATABASE WITH THE RAW CONTENT OF THE FILE … … 191 192 INTEGER, ALLOCATABLE :: ixf(:) !--- File index for each section of the expanded list 192 193 LOGICAL, ALLOCATABLE :: lTg(:) !--- Tagging tracers mask 193 CHARACTER(LEN= 256) :: fnm, snm194 CHARACTER(LEN=maxlen) :: fnm, snm, modname 194 195 INTEGER :: idb, i 195 196 LOGICAL :: ll 196 197 !------------------------------------------------------------------------------------------------------------------------------ 197 198 modname = 'feedDBase' 198 199 !=== READ THE REQUIRED SECTIONS 199 200 ll = strCount(snames, ',', ndb) !--- Number of sections for each file … … 219 220 220 221 !=== DISPLAY BASIC INFORMATION 221 lerr = ANY([(dispTraSection('Expanded list for section "'//TRIM(dBase(idb)%name)//'"',dBase(idb)%name), idb=1, SIZE(dBase))]) 222 lerr = ANY([( dispTraSection('Expanded list for section "'//TRIM(dBase(idb)%name)//'"', dBase(idb)%name, modname), & 223 idb=1, SIZE(dBase) )]) 222 224 END FUNCTION feedDBase 223 225 !------------------------------------------------------------------------------------------------------------------------------ … … 230 232 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: defName !--- Special section (default values) name 231 233 !------------------------------------------------------------------------------------------------------------------------------ 232 TYPE(d b),ALLOCATABLE :: tdb(:)233 CHARACTER(LEN= 256), ALLOCATABLE :: sec(:)234 INTEGER, ALLOCATABLE :: ix(:)234 TYPE(dataBase_type), ALLOCATABLE :: tdb(:) 235 CHARACTER(LEN=maxlen), ALLOCATABLE :: sec(:) 236 INTEGER, ALLOCATABLE :: ix(:) 235 237 INTEGER :: n0, idb, ndb, i, j 236 238 LOGICAL :: ll … … 252 254 SUBROUTINE readSections_all() 253 255 !------------------------------------------------------------------------------------------------------------------------------ 254 CHARACTER(LEN= 256), ALLOCATABLE :: s(:), v(:)255 TYPE(tra ),ALLOCATABLE :: tt(:)256 TYPE(tra ):: tmp257 CHARACTER(LEN=1024) :: str258 CHARACTER(LEN= 256):: secn259 INTEGER :: ierr, n256 CHARACTER(LEN=maxlen), ALLOCATABLE :: s(:), v(:) 257 TYPE(trac_type), ALLOCATABLE :: tt(:) 258 TYPE(trac_type) :: tmp 259 CHARACTER(LEN=1024) :: str 260 CHARACTER(LEN=maxlen) :: secn 261 INTEGER :: ierr, n 260 262 !------------------------------------------------------------------------------------------------------------------------------ 261 263 IF(.NOT.ALLOCATED(dBase)) ALLOCATE(dBase(0)) … … 280 282 ll = strParse(str,' ', keys = s, vals = v, n = n) !--- Parse <key>=<val> pairs 281 283 tt = dBase(ndb)%trac(:) 282 tmp%name = s(1); tmp%comp =secn; tmp%keys = kys(s(1), s(2:n), v(2:n))284 tmp%name = s(1); tmp%component=secn; tmp%keys = keys_type(s(1), s(2:n), v(2:n)) 283 285 dBase(ndb)%trac = [tt(:), tmp] 284 286 DEALLOCATE(tt) 285 ! dBase(ndb)%trac = [dBase(ndb)%trac(:), tra(name=s(1), comp=secn, keys=k ys(s(1), s(2:n), v(2:n)))]287 ! dBase(ndb)%trac = [dBase(ndb)%trac(:), tra(name=s(1), comp=secn, keys=keys_type(s(1), s(2:n), v(2:n)))] 286 288 END IF 287 289 END DO … … 300 302 ! Purpose: Add the keys from virtual tracer named "defName" (if any) and remove this virtual tracer. 301 303 !------------------------------------------------------------------------------------------------------------------------------ 302 TYPE(tra ), ALLOCATABLE, TARGET, INTENT(INOUT) :: t(:)303 CHARACTER(LEN=*), INTENT(IN) :: defName304 TYPE(trac_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: t(:) 305 CHARACTER(LEN=*), INTENT(IN) :: defName 304 306 INTEGER :: jd, it, k 305 TYPE(k ys), POINTER :: ky306 TYPE(tra ), ALLOCATABLE :: tt(:)307 TYPE(keys_type), POINTER :: ky 308 TYPE(trac_type), ALLOCATABLE :: tt(:) 307 309 jd = strIdx(t(:)%name, defName) 308 310 IF(jd == 0) RETURN … … 321 323 ! Substitute the keys locally (for the current tracer) if the flag "lSubLocal" is .TRUE. 322 324 !------------------------------------------------------------------------------------------------------------------------------ 323 TYPE(tra ), ALLOCATABLE, TARGET, INTENT(INOUT) :: t(:)324 CHARACTER(LEN=*), INTENT(IN) :: defName325 LOGICAL, INTENT(IN) :: lSubLocal325 TYPE(trac_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: t(:) 326 CHARACTER(LEN=*), INTENT(IN) :: defName 327 LOGICAL, INTENT(IN) :: lSubLocal 326 328 INTEGER :: i0, it, ik 327 TYPE(k ys), POINTER :: k0, ky328 TYPE(tra ), ALLOCATABLE :: tt(:)329 TYPE(keys_type), POINTER :: k0, ky 330 TYPE(trac_type), ALLOCATABLE :: tt(:) 329 331 i0 = strIdx(t(:)%name, defName) 330 332 IF(i0 == 0) RETURN … … 353 355 ! * Default values are provided for these keys because they are necessary. 354 356 !------------------------------------------------------------------------------------------------------------------------------ 355 TYPE(tra ),ALLOCATABLE, INTENT(INOUT) :: tr(:) !--- Tracer derived type vector356 CHARACTER(LEN=*), INTENT(IN) :: sname357 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: fname358 TYPE(tra ),ALLOCATABLE :: ttr(:)359 CHARACTER(LEN= 256), ALLOCATABLE :: ta(:), pa(:)360 CHARACTER(LEN= 256) :: msg1357 TYPE(trac_type), ALLOCATABLE, INTENT(INOUT) :: tr(:) !--- Tracer derived type vector 358 CHARACTER(LEN=*), INTENT(IN) :: sname 359 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: fname 360 TYPE(trac_type), ALLOCATABLE :: ttr(:) 361 CHARACTER(LEN=maxlen), ALLOCATABLE :: ta(:), pa(:) 362 CHARACTER(LEN=maxlen) :: msg1, modname 361 363 INTEGER :: it, nt, iq, nq, itr, ntr, ipr, npr, i 362 364 LOGICAL :: ll 365 modname = 'expandSection' 363 366 lerr = .FALSE. 364 367 nt = SIZE(tr) … … 368 371 !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 369 372 !--- Extract useful keys: parent name, type, component name 370 tr(it)%p rnt= fgetKey(it, 'parent', tr(:)%keys, tran0 )371 tr(it)%type = fgetKey(it, 'type' , tr(:)%keys, 'tracer')372 tr(it)%comp = sname373 tr(it)%parent = fgetKey(it, 'parent', tr(:)%keys, tran0 ) 374 tr(it)%type = fgetKey(it, 'type' , tr(:)%keys, 'tracer') 375 tr(it)%component = sname 373 376 374 377 !--- Determine the number of tracers and parents ; coherence checking 375 ll = strCount(tr(it)%name, ',', ntr)376 ll = strCount(tr(it)%p rnt, ',', npr)378 ll = strCount(tr(it)%name, ',', ntr) 379 ll = strCount(tr(it)%parent, ',', npr) 377 380 378 381 !--- Tagging tracers only can have multiple parents … … 380 383 msg1 = 'Check section "'//TRIM(sname)//'"' 381 384 IF(PRESENT(fname)) msg1=TRIM(msg1)//' in file "'//TRIM(fname)//'"' 382 CALL msg(TRIM(msg1)//': "'//TRIM(tr(it)%name)//'" has several parents but is not a tag' ); RETURN385 CALL msg(TRIM(msg1)//': "'//TRIM(tr(it)%name)//'" has several parents but is not a tag', modname); RETURN 383 386 END IF 384 387 nq = nq + ntr*npr … … 394 397 !++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 395 398 ll = strParse(tr(it)%name, ',', ta, n=ntr) !--- Number of tracers 396 ll = strParse(tr(it)%p rnt, ',', pa, n=npr)!--- Number of parents399 ll = strParse(tr(it)%parent, ',', pa, n=npr) !--- Number of parents 397 400 DO ipr=1,npr !--- Loop on parents list elts 398 401 DO itr=1,ntr !--- Loop on tracers list elts 399 402 i = iq+itr-1+(ipr-1)*ntr 400 ttr(i)%name = ta(itr); ttr(i)%p rnt = pa(ipr)401 ttr(i)%keys = k ys(ta(itr), tr(it)%keys%key, tr(it)%keys%val)403 ttr(i)%name = ta(itr); ttr(i)%parent = pa(ipr) 404 ttr(i)%keys = keys_type(ta(itr), tr(it)%keys%key, tr(it)%keys%val) 402 405 END DO 403 406 END DO … … 421 424 !------------------------------------------------------------------------------------------------------------------------------ 422 425 ! Arguments: 423 TYPE(tra ), INTENT(INOUT) :: tr(:)!--- Tracer derived type vector426 TYPE(trac_type), INTENT(INOUT) :: tr(:) !--- Tracer derived type vector 424 427 !------------------------------------------------------------------------------------------------------------------------------ 425 428 ! Local variables: 426 429 INTEGER :: iq, nq, ig 427 LOGICAL, ALLOCATABLE :: lg(:)428 CHARACTER(LEN= 256), ALLOCATABLE :: prn(:)429 !------------------------------------------------------------------------------------------------------------------------------ 430 tr(:)%i gen = 0!--- error if 0430 LOGICAL, ALLOCATABLE :: lg(:) 431 CHARACTER(LEN=maxlen), ALLOCATABLE :: prn(:) 432 !------------------------------------------------------------------------------------------------------------------------------ 433 tr(:)%iGeneration = 0 !--- error if 0 431 434 nq = SIZE(tr, DIM=1) !--- Number of tracers lines 432 lg = tr(:)%p rnt == tran0!--- First generation tracers flag433 WHERE(lg) tr(:)%i gen = 1!--- First generation tracers435 lg = tr(:)%parent == tran0 !--- First generation tracers flag 436 WHERE(lg) tr(:)%iGeneration = 1 !--- First generation tracers 434 437 435 438 !=== Determine generation for each tracer 436 439 ig=0; prn = [tran0] 437 440 DO !--- Update current generation flag 438 IF(ig/=0) prn = PACK( tr(:)%name, MASK=tr(:)%i gen == ig)439 lg(:) = [(ANY(prn(:) == tr(iq)%p rnt), iq=1, nq)]!--- Current generation tracers flag441 IF(ig/=0) prn = PACK( tr(:)%name, MASK=tr(:)%iGeneration == ig) 442 lg(:) = [(ANY(prn(:) == tr(iq)%parent), iq=1, nq)] !--- Current generation tracers flag 440 443 IF( ALL( .NOT. lg ) ) EXIT !--- Empty current generation 441 ig = ig+1; WHERE(lg) tr(:)%i gen = ig442 END DO 443 tr(:)% nam1 = ancestor(tr)!--- First generation ancestor name444 ig = ig+1; WHERE(lg) tr(:)%iGeneration = ig 445 END DO 446 tr(:)%gen0Name = ancestor(tr) !--- First generation ancestor name 444 447 445 448 END SUBROUTINE setGeneration … … 453 456 ! * check wether the phases are known or not ("g"aseous, "l"iquid or "s"olid so far) 454 457 !------------------------------------------------------------------------------------------------------------------------------ 455 TYPE(tra ),INTENT(IN) :: tr(:) !--- Tracer derived type vector458 TYPE(trac_type), INTENT(IN) :: tr(:) !--- Tracer derived type vector 456 459 CHARACTER(LEN=*), INTENT(IN) :: sname !--- Section name 457 460 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: fname !--- File name 458 CHARACTER(LEN= 256) :: mesg459 CHARACTER(LEN= 256) :: bp(SIZE(tr, DIM=1)), pha!--- Bad phases list, phases of current tracer461 CHARACTER(LEN=maxlen) :: mesg 462 CHARACTER(LEN=maxlen) :: bp(SIZE(tr, DIM=1)), pha !--- Bad phases list, phases of current tracer 460 463 CHARACTER(LEN=1) :: p 461 464 INTEGER :: ip, np, iq, nq … … 466 469 467 470 !=== CHECK FOR ORPHAN TRACERS 468 IF(test(checkList(tr%name, tr%i gen==0, mesg, 'tracers', 'orphan'), lerr)) RETURN471 IF(test(checkList(tr%name, tr%iGeneration==0, mesg, 'tracers', 'orphan'), lerr)) RETURN 469 472 470 473 !=== CHECK PHASES 471 DO iq=1,nq; IF(tr(iq)%i gen/=1) CYCLE!--- Generation 1 only is checked474 DO iq=1,nq; IF(tr(iq)%iGeneration/=1) CYCLE !--- Generation 1 only is checked 472 475 pha = fgetKey(iq, 'phases', tr(:)%keys, 'g') !--- Phases 473 476 np = LEN_TRIM(pha); bp(iq)=' ' … … 475 478 IF(TRIM(bp(iq)) /= '') bp(iq) = TRIM(tr(iq)%name)//': '//TRIM(bp(iq)) 476 479 END DO 477 lerr = checkList(bp, tr%i gen==1 .AND. bp/='', mesg, 'tracers phases', 'unknown')480 lerr = checkList(bp, tr%iGeneration==1 .AND. bp/='', mesg, 'tracers phases', 'unknown') 478 481 END FUNCTION checkTracers 479 482 !============================================================================================================================== … … 484 487 ! Purpose: Make sure that tracers are not repeated. 485 488 !------------------------------------------------------------------------------------------------------------------------------ 486 TYPE(tra ),INTENT(IN) :: tr(:) !--- Tracer derived type vector489 TYPE(trac_type), INTENT(IN) :: tr(:) !--- Tracer derived type vector 487 490 LOGICAL, INTENT(IN) :: lTag(:) !--- Tagging tracer flag 488 491 CHARACTER(LEN=*), INTENT(IN) :: sname !--- Section name … … 490 493 !------------------------------------------------------------------------------------------------------------------------------ 491 494 INTEGER :: ip, np, iq, nq, k 492 LOGICAL, ALLOCATABLE :: ll(:)493 CHARACTER(LEN= 256) :: mesg, tnam, tdup(SIZE(tr,DIM=1))494 CHARACTER(LEN=1) :: p495 LOGICAL, ALLOCATABLE :: ll(:) 496 CHARACTER(LEN=maxlen) :: mesg, tnam, tdup(SIZE(tr,DIM=1)) 497 CHARACTER(LEN=1) :: p 495 498 !------------------------------------------------------------------------------------------------------------------------------ 496 499 mesg = 'Check section "'//TRIM(sname)//'"' … … 502 505 ll = tr(:)%name==tnam !--- Mask for current tracer name 503 506 IF(COUNT(ll)==1 ) CYCLE !--- Tracer is not repeated 504 IF(tr(iq)%i gen>1) THEN507 IF(tr(iq)%iGeneration>1) THEN 505 508 tdup(iq) = tnam !--- gen>1: MUST be unique 506 509 ELSE … … 524 527 ! Purpose: Expand the phases in the tracers descriptor "tr". 525 528 !------------------------------------------------------------------------------------------------------------------------------ 526 TYPE(tra ), ALLOCATABLE, INTENT(INOUT) :: tr(:)!--- Tracer derived type vector527 !------------------------------------------------------------------------------------------------------------------------------ 528 TYPE(tra ), ALLOCATABLE :: ttr(:)529 INTEGER, ALLOCATABLE :: i0(:)530 CHARACTER(LEN= 256):: nam, pha, trn529 TYPE(trac_type), ALLOCATABLE, INTENT(INOUT) :: tr(:) !--- Tracer derived type vector 530 !------------------------------------------------------------------------------------------------------------------------------ 531 TYPE(trac_type), ALLOCATABLE :: ttr(:) 532 INTEGER, ALLOCATABLE :: i0(:) 533 CHARACTER(LEN=maxlen) :: nam, pha, trn 531 534 INTEGER :: ip, np, iq, jq, nq, it, nt, nc, i, n 532 535 LOGICAL :: lTg, lEx … … 535 538 nt = 0 536 539 DO iq = 1, nq !--- GET THE NUMBER OF TRACERS 537 IF(tr(iq)%i gen /= 1) CYCLE538 nc = COUNT(tr(:)% nam1==tr(iq)%name .AND. tr%igen/=1)!--- Number of childs of tr(iq)539 tr(iq)%phas = fgetKey(iq, 'phases', tr(:)%keys)!--- Phases list of tr(iq)540 np = LEN_TRIM(tr(iq)%phas )!--- Number of phases of tr(iq)540 IF(tr(iq)%iGeneration /= 1) CYCLE 541 nc = COUNT(tr(:)%gen0Name==tr(iq)%name .AND. tr%iGeneration/=1) !--- Number of childs of tr(iq) 542 tr(iq)%phase = fgetKey(iq, 'phases', tr(:)%keys) !--- Phases list of tr(iq) 543 np = LEN_TRIM(tr(iq)%phase) !--- Number of phases of tr(iq) 541 544 nt = nt + (1+nc) * np !--- Number of tracers after expansion 542 545 END DO … … 545 548 DO iq = 1, nq !--- Loop on "tr(:)" indexes 546 549 lTg = tr(iq)%type=='tag' !--- Current tracer is a tag 547 i0 = strFind(tr(:)%name, tr(iq)% nam1, n)!--- Indexes of first generation ancestor copies548 np = SUM( [( LEN_TRIM(tr(i0(i))%phas ),i=1,n )],1)!--- Number of phases for current tracer tr(iq)550 i0 = strFind(tr(:)%name, tr(iq)%gen0Name, n) !--- Indexes of first generation ancestor copies 551 np = SUM( [( LEN_TRIM(tr(i0(i))%phase),i=1,n )],1) !--- Number of phases for current tracer tr(iq) 549 552 lEx = np>1 !--- Need of a phase suffix 550 IF(lTg) lEx=lEx.AND.tr(iq)%i gen>1!--- No phase suffix for first generation tags553 IF(lTg) lEx=lEx.AND.tr(iq)%iGeneration>1 !--- No phase suffix for first generation tags 551 554 DO i=1,n !=== LOOP ON FIRST GENERATION ANCESTORS 552 555 jq=i0(i) !--- tr(jq): ith copy of 1st gen. ancestor of tr(iq) 553 IF(tr(iq)%i gen==1) jq=iq!--- Generation 1: current tracer phases only554 pha = tr(jq)%phas 556 IF(tr(iq)%iGeneration==1) jq=iq !--- Generation 1: current tracer phases only 557 pha = tr(jq)%phase !--- Phases list for tr(jq) 555 558 DO ip=1,LEN_TRIM(pha) !=== LOOP ON PHASES LISTS 556 559 trn=TRIM(tr(iq)%name); nam=trn !--- Tracer name (regular case) 557 IF(lTg) nam = TRIM(tr(iq)%p rnt)!--- Parent name (tagging case)560 IF(lTg) nam = TRIM(tr(iq)%parent) !--- Parent name (tagging case) 558 561 IF(lEx) nam = TRIM(nam)//phases_sep//pha(ip:ip) !--- Phase extension needed 559 562 IF(lTg) nam = TRIM(nam)//'_'//TRIM(trn) !--- <parent>_<name> for tags … … 561 564 ttr(it)%name = nam !--- Name with possibly phase suffix 562 565 ttr(it)%keys%name = nam !--- Name inside the keys decriptor 563 ttr(it)%phas = pha(ip:ip)!--- Single phase entry564 IF(lEx.AND.tr(iq)%i gen>1) THEN565 ttr(it)%p rnt = TRIM(ttr(it)%prnt)//phases_sep//pha(ip:ip)566 ttr(it)% nam1 = TRIM(ttr(it)%nam1)//phases_sep//pha(ip:ip)566 ttr(it)%phase = pha(ip:ip) !--- Single phase entry 567 IF(lEx.AND.tr(iq)%iGeneration>1) THEN 568 ttr(it)%parent = TRIM(ttr(it)%parent)//phases_sep//pha(ip:ip) 569 ttr(it)%gen0Name = TRIM(ttr(it)%gen0Name)//phases_sep//pha(ip:ip) 567 570 END IF 568 571 it=it+1 569 572 END DO 570 IF(tr(iq)%i gen==1) EXIT!--- Break phase loop for gen 1573 IF(tr(iq)%iGeneration==1) EXIT !--- Break phase loop for gen 1 571 574 END DO 572 575 END DO … … 584 587 ! * lGrowGen == F: tracer + its childs sorted by growing generation, one after the other. 585 588 !------------------------------------------------------------------------------------------------------------------------------ 586 TYPE(tra ), ALLOCATABLE, INTENT(INOUT) :: tr(:)!--- Tracer derived type vector589 TYPE(trac_type), ALLOCATABLE, INTENT(INOUT) :: tr(:) !--- Tracer derived type vector 587 590 INTEGER :: ig, ng, iq, jq, n, ix(SIZE(tr)), k 588 591 INTEGER, ALLOCATABLE :: iy(:), iz(:) … … 590 593 iq = 1 591 594 IF(lSortByGen) THEN 592 ng = MAXVAL(tr(:)%i gen, MASK=.TRUE., DIM=1)!--- Number of generations595 ng = MAXVAL(tr(:)%iGeneration, MASK=.TRUE., DIM=1) !--- Number of generations 593 596 DO ig = 0, ng !--- Loop on generations 594 iy = PACK([(k, k=1, SIZE(tr))], MASK=tr(:)%i gen==ig)!--- Generation ig tracers indexes597 iy = PACK([(k, k=1, SIZE(tr))], MASK=tr(:)%iGeneration==ig) !--- Generation ig tracers indexes 595 598 n = SIZE(iy) 596 599 ix(iq:iq+n-1) = iy !--- Stack growing generations idxs … … 599 602 ELSE 600 603 DO jq = 1, SIZE(tr,DIM=1) !--- Loop on first generation tracers 601 IF(tr(jq)%i gen /= 1) CYCLE!--- Skip generations >= 1604 IF(tr(jq)%iGeneration /= 1) CYCLE !--- Skip generations >= 1 602 605 ix(iq) = jq !--- First generation ancestor index first 603 606 iq = iq + 1 604 iy = strFind(tr(:)% nam1, tr(jq)%name)!--- Indexes of "tr(jq)" childs in "tr(:)"605 ng = MAXVAL(tr(iy)%i gen, MASK=.TRUE., DIM=1)!--- Generations number of the "tr(jq)" family607 iy = strFind(tr(:)%gen0Name, tr(jq)%name) !--- Indexes of "tr(jq)" childs in "tr(:)" 608 ng = MAXVAL(tr(iy)%iGeneration, MASK=.TRUE., DIM=1) !--- Generations number of the "tr(jq)" family 606 609 DO ig = 2, ng !--- Loop on generations for the tr(jq) family 607 iz = find(tr(iy)%i gen, ig, n)!--- Indexes of the tracers "tr(iy(:))" of generation "ig"610 iz = find(tr(iy)%iGeneration, ig, n) !--- Indexes of the tracers "tr(iy(:))" of generation "ig" 608 611 ix(iq:iq+n-1) = iy(iz) !--- Same indexes in "tr(:)" 609 612 iq = iq + n … … 617 620 !============================================================================================================================== 618 621 LOGICAL FUNCTION mergeTracers(sections, tr) RESULT(lerr) 619 TYPE(d b), TARGET,INTENT(IN) :: sections(:)620 TYPE(tra ), ALLOCATABLE, INTENT(OUT) :: tr(:)621 TYPE(tra ), POINTER:: t1(:), t2(:)622 INTEGER, ALLOCATABLE :: ixct(:), ixck(:)622 TYPE(dataBase_type), TARGET, INTENT(IN) :: sections(:) 623 TYPE(trac_type), ALLOCATABLE, INTENT(OUT) :: tr(:) 624 TYPE(trac_type), POINTER :: t1(:), t2(:) 625 INTEGER, ALLOCATABLE :: ixct(:), ixck(:) 623 626 INTEGER :: is, k1, k2, nk2, i1, i2, nt2 624 CHARACTER(LEN=256) :: s1, v1, v2, tnam, knam 627 CHARACTER(LEN=maxlen) :: s1, v1, v2, tnam, knam, modname 628 modname = 'mergeTracers' 625 629 lerr = .FALSE. 626 630 t1 => sections(1)%trac(:) !--- Alias: first tracers section … … 634 638 tr = [tr, PACK(t2, MASK= ixct==0)] !--- Append with new tracers 635 639 IF( ALL(ixct == 0) ) CYCLE !--- No common tracers => done 636 CALL msg('Tracers defined in previous sections and duplicated in "'//TRIM(sections(is)%name)//'":' )637 CALL msg( t1(PACK(ixct, MASK = ixct/=0))%name, nmax=128 )!--- Display duplicates (the 128 first at most)640 CALL msg('Tracers defined in previous sections and duplicated in "'//TRIM(sections(is)%name)//'":', modname) 641 CALL msg(t1(PACK(ixct, MASK = ixct/=0))%name, modname, nmax=128) !--- Display duplicates (the 128 first at most) 638 642 !-------------------------------------------------------------------------------------------------------------------------- 639 643 DO i2=1,nt2; tnam = t2(i2)%name !=== LOOP ON COMMON TRACERS … … 644 648 s1=' of "'//TRIM(tnam)//'" in "'//TRIM(sections(is)%name)//'" not matching previous value' 645 649 646 IF(test(fmsg( t1(i1)%prnt /= t2(i2)%prnt, 'Parent name'//TRIM(s1)),lerr)) RETURN647 IF(test(fmsg( t1(i1)%type /= t2(i2)%type, 'Type' //TRIM(s1)),lerr)) RETURN648 IF(test(fmsg( t1(i1)%igen /= t2(i2)%igen, 'Generation' //TRIM(s1)), lerr)) RETURN650 IF(test(fmsg('Parent name'//TRIM(s1), modname, t1(i1)%parent /= t2(i2)%parent), lerr)) RETURN 651 IF(test(fmsg('Type' //TRIM(s1), modname, t1(i1)%type /= t2(i2)%type), lerr)) RETURN 652 IF(test(fmsg('Generation' //TRIM(s1), modname, t1(i1)%iGeneration /= t2(i2)%iGeneration), lerr)) RETURN 649 653 650 654 !=== APPEND <key>=<val> PAIRS NOT PREVIOULSLY DEFINED … … 657 661 658 662 !--- KEEP TRACK OF THE COMPONENTS NAMES 659 tr(i1)%comp = TRIM(tr(i1)%comp)//','//TRIM(tr(i2)%comp)663 tr(i1)%component = TRIM(tr(i1)%component)//','//TRIM(tr(i2)%component) 660 664 661 665 !--- SELECT COMMON TRACERS WITH DIFFERING KEYS VALUES (PREVIOUS VALUE IS KEPT) … … 667 671 668 672 !--- DISPLAY INFORMATION: OLD VALUES ARE KEPT FOR THE KEYS FOUND IN PREVIOUS AND CURRENT SECTIONS 669 CALL msg('Key(s)'//TRIM(s1) )673 CALL msg('Key(s)'//TRIM(s1), modname) 670 674 DO k2 = 1, nk2 !--- Loop on keys found in both t1(:) and t2(:) 671 675 knam = t2(i2)%keys%key(k2) !--- Name of the current key … … 673 677 IF(k1 == 0) CYCLE !--- New keys are skipped 674 678 v1 = t1(i1)%keys%val(k1); v2 = t2(i2)%keys%val(k2) !--- Key values in t1(:) and t2(:) 675 CALL msg(' * '//TRIM(knam)//'='//TRIM(v2)//' ; previous value kept:'//TRIM(v1) )679 CALL msg(' * '//TRIM(knam)//'='//TRIM(v2)//' ; previous value kept:'//TRIM(v1), modname) 676 680 END DO 677 681 !------------------------------------------------------------------------------------------------------------------------ … … 686 690 !============================================================================================================================== 687 691 LOGICAL FUNCTION cumulTracers(sections, tr) RESULT(lerr) 688 TYPE(d b), TARGET,INTENT(IN) :: sections(:)689 TYPE(tra ), ALLOCATABLE, INTENT(OUT) :: tr(:)690 TYPE(tra ), POINTER :: t1(:), t2(:)692 TYPE(dataBase_type), TARGET, INTENT(IN) :: sections(:) 693 TYPE(trac_type), ALLOCATABLE, INTENT(OUT) :: tr(:) 694 TYPE(trac_type), POINTER :: t1(:), t2(:) 691 695 INTEGER, ALLOCATABLE :: nt(:) 692 CHARACTER(LEN= 256):: tnam, tnam_new696 CHARACTER(LEN=maxlen) :: tnam, tnam_new 693 697 INTEGER :: iq, nq, is, ns, nsec 694 698 lerr = .FALSE. !--- Can't fail ; kept to match "mergeTracer" interface. … … 709 713 ns = nt(is) !--- Number of tracers in the current section 710 714 tr(iq + nq)%name = tnam_new !--- Modify tracer name 711 WHERE(tr(1+nq:ns+nq)%p rnt==tnam) tr(1+nq:ns+nq)%prnt=tnam_new !--- Modify parent name715 WHERE(tr(1+nq:ns+nq)%parent==tnam) tr(1+nq:ns+nq)%parent=tnam_new !--- Modify parent name 712 716 !-------------------------------------------------------------------------------------------------------------------------- 713 717 END DO … … 721 725 !============================================================================================================================== 722 726 SUBROUTINE setDirectKeys(tr) 723 TYPE(tra ), INTENT(INOUT) :: tr(:)724 CALL indexUpdate(tr) !--- Update i parnt and idescindexes vectors727 TYPE(trac_type), INTENT(INOUT) :: tr(:) 728 CALL indexUpdate(tr) !--- Update iqParent and iqDescen indexes vectors 725 729 ! DO iq = 1, SIZE(tr) 726 730 ! tr(iq)%keys%<key> = getKey_prv(it, "<key>", tr%keys, tran0 ) !--- For additional keys … … 730 734 731 735 !============================================================================================================================== 732 LOGICAL FUNCTION dispTraSection(message, sname) RESULT(lerr) 733 CHARACTER(LEN=*), INTENT(IN) :: message 734 CHARACTER(LEN=*), INTENT(IN) :: sname 736 LOGICAL FUNCTION dispTraSection(message, sname, modname) RESULT(lerr) 737 CHARACTER(LEN=*), INTENT(IN) :: message, sname, modname 735 738 INTEGER :: idb, iq, nq 736 739 INTEGER, ALLOCATABLE :: hadv(:), vadv(:) 737 TYPE(tra ), POINTER :: tm(:)740 TYPE(trac_type), POINTER :: tm(:) 738 741 lerr = .FALSE. 739 742 idb = strIdx(dBase(:)%name, sname); IF(idb == 0) RETURN … … 742 745 IF(test(getKeyByName_im('hadv', hadv, tm(:)%name, tm(:)%keys),lerr)) RETURN 743 746 IF(test(getKeyByName_im('vadv', vadv, tm(:)%name, tm(:)%keys),lerr)) RETURN 744 CALL msg(TRIM(message)//':' )747 CALL msg(TRIM(message)//':', modname) 745 748 IF(test(dispTable('iiissis', ['iq ','hadv ','vadv ','short name','parent ','igen ','phase '], & 746 cat(tm(:)%name, tm(:)%prnt, tm(:)%phas), cat([(iq, iq=1, nq)], hadv, vadv, tm(:)%igen)), lerr)) RETURN749 cat(tm(:)%name, tm(:)%parent, tm(:)%phase), cat([(iq, iq=1, nq)], hadv, vadv, tm(:)%iGeneration)), lerr)) RETURN 747 750 END FUNCTION dispTraSection 748 751 !============================================================================================================================== … … 754 757 !============================================================================================================================== 755 758 FUNCTION aliasTracer(tname, t) RESULT(out) 756 TYPE(tra ), POINTER :: out757 CHARACTER(LEN=*), INTENT(IN) :: tname758 TYPE(tra ), TARGET, INTENT(IN) :: t(:)759 TYPE(trac_type), POINTER :: out 760 CHARACTER(LEN=*), INTENT(IN) :: tname 761 TYPE(trac_type), TARGET, INTENT(IN) :: t(:) 759 762 INTEGER :: it 760 763 it = strIdx(t(:)%name, tname) … … 768 771 !============================================================================================================================== 769 772 FUNCTION trSubset_Indx(trac,idx) RESULT(out) 770 TYPE(tra ), ALLOCATABLE :: out(:)771 TYPE(tra ), ALLOCATABLE, INTENT(IN) :: trac(:)772 INTEGER, INTENT(IN) :: idx(:)773 TYPE(trac_type), ALLOCATABLE :: out(:) 774 TYPE(trac_type), ALLOCATABLE, INTENT(IN) :: trac(:) 775 INTEGER, INTENT(IN) :: idx(:) 773 776 out = trac(idx) 774 777 CALL indexUpdate(out) … … 776 779 !------------------------------------------------------------------------------------------------------------------------------ 777 780 FUNCTION trSubset_Name(trac,nam) RESULT(out) 778 TYPE(tra ), ALLOCATABLE :: out(:)779 TYPE(tra ), ALLOCATABLE, INTENT(IN) :: trac(:)780 CHARACTER(LEN=*), INTENT(IN) :: nam(:)781 TYPE(trac_type), ALLOCATABLE :: out(:) 782 TYPE(trac_type), ALLOCATABLE, INTENT(IN) :: trac(:) 783 CHARACTER(LEN=*), INTENT(IN) :: nam(:) 781 784 out = trac(strIdx(trac(:)%name, nam)) 782 785 CALL indexUpdate(out) … … 788 791 !=== CREATE THE SUBSET OF THE TRACERS DESCRIPTORS LIST "trac" HAVING THE FIRST GENERATION ANCESTOR NAMED "nam" ================ 789 792 !============================================================================================================================== 790 FUNCTION trSubset_ Nam1(trac,nam) RESULT(out)791 TYPE(tra ), ALLOCATABLE :: out(:)792 TYPE(tra ), ALLOCATABLE, INTENT(IN) :: trac(:)793 CHARACTER(LEN=*), INTENT(IN) :: nam794 out = trac(strFind(delPhase(trac(:)% nam1), nam))793 FUNCTION trSubset_gen0Name(trac,nam) RESULT(out) 794 TYPE(trac_type), ALLOCATABLE :: out(:) 795 TYPE(trac_type), ALLOCATABLE, INTENT(IN) :: trac(:) 796 CHARACTER(LEN=*), INTENT(IN) :: nam 797 out = trac(strFind(delPhase(trac(:)%gen0Name), nam)) 795 798 CALL indexUpdate(out) 796 END FUNCTION trSubset_ Nam1797 !------------------------------------------------------------------------------------------------------------------------------ 798 799 800 !============================================================================================================================== 801 !=== UPDATE THE INDEXES i parnt(:), idesc=(:) AND igen(:) IN THE TRACERS DESCRIPTOR LIST "tr" (USEFULL FOR SUBSETS) ============799 END FUNCTION trSubset_gen0Name 800 !------------------------------------------------------------------------------------------------------------------------------ 801 802 803 !============================================================================================================================== 804 !=== UPDATE THE INDEXES iqParent, iqDescend AND iGeneration IN THE TRACERS DESCRIPTOR LIST "tr" (USEFULL FOR SUBSETS) ========= 802 805 !============================================================================================================================== 803 806 SUBROUTINE indexUpdate(tr) 804 TYPE(tra ), INTENT(INOUT) :: tr(:)807 TYPE(trac_type), INTENT(INOUT) :: tr(:) 805 808 INTEGER :: iq, ig, ng, ngen 806 809 INTEGER, ALLOCATABLE :: ix(:) 807 tr(:)%i prnt = strIdx( tr(:)%name, tr(:)%prnt )!--- Parent index808 ngen = MAXVAL(tr(:)%i gen, MASK=.TRUE.)810 tr(:)%iqParent = strIdx( tr(:)%name, tr(:)%parent ) !--- Parent index 811 ngen = MAXVAL(tr(:)%iGeneration, MASK=.TRUE.) 809 812 DO iq = 1, SIZE(tr) 810 ng = tr(iq)%i gen!--- Generation of the current tracer813 ng = tr(iq)%iGeneration !--- Generation of the current tracer 811 814 ix = idxAncestor(tr, igen = ng); ix = PACK(ix, ix/=0) !--- Indexes of the tracers with ancestor tr(iq) 812 815 !--- Childs indexes in growing generation order 813 tr(iq)%i desc = [( PACK(ix, MASK = tr(ix)%igen == ig), ig = ng+1, ngen)]814 tr(iq)%n desc = SUM( [( COUNT(tr(ix)%igen == ig), ig = ng+1, ngen)] )815 tr(iq)%n chld = COUNT(tr(ix)%igen == ng+1)816 tr(iq)%iqDescen = [( PACK(ix, MASK = tr(ix)%iGeneration == ig), ig = ng+1, ngen)] 817 tr(iq)%nqDescen = SUM( [( COUNT(tr(ix)%iGeneration == ig), ig = ng+1, ngen)] ) 818 tr(iq)%nqChilds = COUNT(tr(ix)%iGeneration == ng+1) 816 819 END DO 817 820 END SUBROUTINE indexUpdate … … 820 823 821 824 !============================================================================================================================== 822 !=== READ FILE "fnam" TO APPEND THE "dBase" TRACERS DATABASE WITH AS MUCH SECTIONS AS PARENTS NAMES IN "isot(:)%p rnt":====823 !=== * Each section dBase(i)%name contains the isotopes "dBase(i)%trac(:)" descending on "dBase(i)%name"="iso(i)%p rnt"====825 !=== READ FILE "fnam" TO APPEND THE "dBase" TRACERS DATABASE WITH AS MUCH SECTIONS AS PARENTS NAMES IN "isot(:)%parent": ==== 826 !=== * Each section dBase(i)%name contains the isotopes "dBase(i)%trac(:)" descending on "dBase(i)%name"="iso(i)%parent" ==== 824 827 !=== * For each isotopes class, the <key>=<val> vector of each tracer is moved into the isotopes descriptor "isot" ==== 825 828 !=== NOTES: ==== … … 833 836 !============================================================================================================================== 834 837 LOGICAL FUNCTION readIsotopesFile(fnam, isot) RESULT(lerr) 835 CHARACTER(LEN=*), INTENT(IN) :: fnam!--- Input file name836 TYPE(iso ), TARGET, INTENT(INOUT) :: isot(:)!--- Isotopes descriptors (field "prnt" must be defined !)838 CHARACTER(LEN=*), INTENT(IN) :: fnam !--- Input file name 839 TYPE(isot_type), TARGET, INTENT(INOUT) :: isot(:) !--- Isotopes descriptors (field "prnt" must be defined !) 837 840 INTEGER :: ik, is, it, idb, nk0, i, iis 838 841 INTEGER :: nk, ns, nt, ndb, nb0, i0 839 CHARACTER(LEN=256), POINTER :: k(:), v(:), k0(:), v0(:) 840 CHARACTER(LEN=256), ALLOCATABLE :: vals(:) 841 CHARACTER(LEN=256) :: val 842 TYPE(kys), POINTER :: ky(:) 843 TYPE(tra), POINTER :: tt(:), t 844 TYPE(db), ALLOCATABLE :: tdb(:) 845 LOGICAL, ALLOCATABLE :: liso(:) 842 CHARACTER(LEN=maxlen), POINTER :: k(:), v(:), k0(:), v0(:) 843 CHARACTER(LEN=maxlen), ALLOCATABLE :: vals(:) 844 CHARACTER(LEN=maxlen) :: val, modname 845 TYPE(keys_type), POINTER :: ky(:) 846 TYPE(trac_type), POINTER :: tt(:), t 847 TYPE(dataBase_type), ALLOCATABLE :: tdb(:) 848 LOGICAL, ALLOCATABLE :: liso(:) 849 modname = 'readIsotopesFile' 846 850 847 851 !--- THE INPUT FILE MUST BE PRESENT 848 IF(test(fmsg( testFile(fnam),'Missing isotopes parameters file "'//TRIM(fnam)//'"'),lerr)) RETURN852 IF(test(fmsg('Missing isotopes parameters file "'//TRIM(fnam)//'"', modname, testFile(fnam)),lerr)) RETURN 849 853 850 854 !--- READ THE FILE SECTIONS, ONE EACH PARENT TRACER 851 855 nb0 = SIZE(dBase, DIM=1)+1 !--- Next database element index 852 IF(test(readSections(fnam,strStack(isot(:)%p rnt,',')),lerr)) RETURN!--- Read sections, one each parent tracer856 IF(test(readSections(fnam,strStack(isot(:)%parent,',')),lerr)) RETURN !--- Read sections, one each parent tracer 853 857 ndb = SIZE(dBase, DIM=1) !--- Current database size 854 858 DO idb = nb0, ndb … … 886 890 ALLOCATE(tdb(nb0-1)); tdb(1:nb0-1)=dBase(1:nb0-1); CALL MOVE_ALLOC(FROM=tdb, TO=dBase) 887 891 END IF 888 lerr = dispIsotopes(isot, 'Isotopes parameters read from file' )892 lerr = dispIsotopes(isot, 'Isotopes parameters read from file', modname) 889 893 890 894 END FUNCTION readIsotopesFile … … 899 903 !============================================================================================================================== 900 904 SUBROUTINE initIsotopes(trac, isot) 901 TYPE(tra ), ALLOCATABLE, TARGET, INTENT(INOUT) :: trac(:)902 TYPE(iso ), ALLOCATABLE, TARGET, INTENT(INOUT) :: isot(:)903 CHARACTER(LEN= 256), ALLOCATABLE :: p(:), str(:)!--- Temporary storage904 CHARACTER(LEN= 256) :: iname905 TYPE(trac_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: trac(:) 906 TYPE(isot_type), ALLOCATABLE, TARGET, INTENT(INOUT) :: isot(:) 907 CHARACTER(LEN=maxlen), ALLOCATABLE :: p(:), str(:) !--- Temporary storage 908 CHARACTER(LEN=maxlen) :: iname 905 909 CHARACTER(LEN=1) :: ph !--- Phase 906 910 INTEGER :: nbIso, ic, ip, iq, it, iz 907 911 LOGICAL, ALLOCATABLE :: ll(:) !--- Mask 908 TYPE(tra ), POINTER :: t(:), t1909 TYPE(iso ), POINTER :: s912 TYPE(trac_type), POINTER :: t(:), t1 913 TYPE(isot_type), POINTER :: s 910 914 911 915 t => trac 912 916 913 p = PACK(delPhase(t%p rnt), MASK = t%type=='tracer' .AND. t%igen==2)!--- Parents of 2nd generation isotopes917 p = PACK(delPhase(t%parent), MASK = t%type=='tracer' .AND. t%iGeneration==2) !--- Parents of 2nd generation isotopes 914 918 CALL strReduce(p, nbIso) 915 919 ALLOCATE(isot(nbIso)) … … 918 922 919 923 !--- ISOTOPES RELATED VARIABLES ; NULL OR EMPTY IF NO ISOTOPES 920 isot(:)%p rnt = p924 isot(:)%parent = p 921 925 DO ic = 1, SIZE(p) !--- Loop on isotopes classes 922 926 s => isot(ic) 923 iname = s%p rnt!--- Current isotopes class name (parent tracer name)927 iname = s%parent !--- Current isotopes class name (parent tracer name) 924 928 925 929 !=== Isotopes childs of tracer "iname": mask, names, number (same for each phase of "iname") 926 ll = t(:)%type=='tracer' .AND. delPhase(t(:)%p rnt) == iname .AND. t(:)%phas== 'g'930 ll = t(:)%type=='tracer' .AND. delPhase(t(:)%parent) == iname .AND. t(:)%phase == 'g' 927 931 str = PACK(delPhase(t(:)%name), MASK = ll) !--- Effectively found isotopes of "iname" 928 932 s%niso = SIZE(str) !--- Number of "effectively found isotopes of "iname" … … 931 935 932 936 !=== Geographic tagging tracers descending on tracer "iname": mask, names, number 933 ll = t(:)%type=='tag' .AND. delPhase(t(:)% nam1) == iname .AND. t(:)%igen == 3937 ll = t(:)%type=='tag' .AND. delPhase(t(:)%gen0Name) == iname .AND. t(:)%iGeneration == 3 934 938 s%zone = PACK(strTail(t(:)%name,'_',lFirst=.TRUE.), MASK = ll) !--- Tagging zones names for isotopes category "iname" 935 939 CALL strReduce(s%zone) … … 946 950 947 951 !=== Phases for tracer "iname" 948 s%phas = ''949 DO ip = 1, nphases; ph = known_phases(ip:ip); IF(strIdx(t%name,addPhase(iname, ph)) /= 0) s%phas = TRIM(s%phas)//ph; END DO950 s%npha = LEN_TRIM(s%phas ) !--- Equal to "nqo" for water952 s%phase = '' 953 DO ip = 1, nphases; ph = known_phases(ip:ip); IF(strIdx(t%name,addPhase(iname, ph)) /= 0) s%phase = TRIM(s%phase)//ph; END DO 954 s%npha = LEN_TRIM(s%phase) !--- Equal to "nqo" for water 951 955 952 956 !=== Tables giving the index in a table of effectively found items for each dynamical tracer (1<=iq<=nqtot) 953 957 DO iq = 1, SIZE(t) 954 958 t1 => trac(iq) 955 IF(delPhase(t1% nam1) /= iname) CYCLE!--- Only deal with tracers descending on "iname"956 t1%iso_i gr = ic !--- Isotopes family idx in list "isotopes(:)%prnt"957 t1%iso_ num = strIdx(s%trac, delPhase(strHead(t1%name,'_')))!--- Current isotope idx in effective isotopes list958 t1%iso_ zon = strIdx(s%zone, strTail(t1%name,'_') )!--- Current isotope zone idx in effective zones list959 t1%iso_ pha = INDEX(s%phas,TRIM(t1%phas))!--- Current isotope phase idx in effective phases list960 IF(t1%i gen /= 3) t1%iso_zon = 0!--- Skip possible generation 2 tagging tracers959 IF(delPhase(t1%gen0Name) /= iname) CYCLE !--- Only deal with tracers descending on "iname" 960 t1%iso_iGroup = ic !--- Isotopes family idx in list "isotopes(:)%parent" 961 t1%iso_iName = strIdx(s%trac, delPhase(strHead(t1%name,'_'))) !--- Current isotope idx in effective isotopes list 962 t1%iso_iZone = strIdx(s%zone, strTail(t1%name,'_') ) !--- Current isotope zone idx in effective zones list 963 t1%iso_iPhase = INDEX(s%phase,TRIM(t1%phase)) !--- Current isotope phase idx in effective phases list 964 IF(t1%iGeneration /= 3) t1%iso_iZone = 0 !--- Skip possible generation 2 tagging tracers 961 965 END DO 962 966 963 967 !=== Table used to get iq (index in dyn array, size nqtot) from the isotope and phase indexes ; the full isotopes list 964 968 ! (including tagging tracers) is sorted this way: iso1, iso2, ..., iso1_zone1, iso2_zone1, ..., iso1_zoneN, iso2_zoneN 965 s%iTraPha = RESHAPE( [( (strIdx(t(:)%name, addPhase(s%trac(it),s%phas (ip:ip))),it=1, s%nitr), ip=1, s%npha)], &969 s%iTraPha = RESHAPE( [( (strIdx(t(:)%name, addPhase(s%trac(it),s%phase(ip:ip))), it=1, s%nitr), ip=1, s%npha)], & 966 970 [s%nitr, s%npha] ) 967 971 … … 970 974 [s%nzon, s%niso] ) 971 975 END DO 972 973 !=== Indexes, in dynamical tracers list, of the tracers transmitted to phytrac (nqtottr non-vanishing elements)974 ll = delPhase(t%name)/='H2O' .AND. t%iso_num ==0 !--- Mask of tracers passed to the physics975 t(:)%itr = UNPACK([(iq,iq=1,COUNT(ll))], ll, [(0, iq=1, SIZE(t))])976 976 977 977 !=== READ PHYSICAL PARAMETERS FROM "isotopes_params.def" FILE … … 984 984 985 985 !============================================================================================================================== 986 LOGICAL FUNCTION dispIsotopes(ides, message ) RESULT(lerr)987 TYPE(iso ),INTENT(IN) :: ides(:) !--- Isotopes descriptor vector986 LOGICAL FUNCTION dispIsotopes(ides, message, modname) RESULT(lerr) 987 TYPE(isot_type), INTENT(IN) :: ides(:) !--- Isotopes descriptor vector 988 988 CHARACTER(LEN=*), INTENT(IN) :: message !--- Message to display 989 CHARACTER(LEN=*), INTENT(IN) :: modname !--- Calling subroutine name 989 990 INTEGER :: ik, nk, ip, it, nt 990 CHARACTER(LEN= 256) :: prf991 CHARACTER(LEN= 256), ALLOCATABLE :: ttl(:), val(:,:)992 CALL msg(TRIM(message)//':' )991 CHARACTER(LEN=maxlen) :: prf 992 CHARACTER(LEN=maxlen), ALLOCATABLE :: ttl(:), val(:,:) 993 CALL msg(TRIM(message)//':', modname) 993 994 DO ip = 1, SIZE(ides) !--- Loop on parents tracers 994 995 nk = SIZE(ides(ip)%keys(1)%key) !--- Same keys for each isotope … … 1003 1004 END DO 1004 1005 END DO 1005 IF(test(fmsg(dispTable(prf, ttl, val, cat([(it,it=1,nt)]), rFmt='(EN8.4)'),'Problem with the table content'), lerr)) RETURN 1006 IF(test(fmsg('Problem with the table content', modname, dispTable(prf, ttl, val, cat([(it,it=1,nt)]), rFmt='(EN8.4)')), & 1007 lerr)) RETURN 1006 1008 DEALLOCATE(ttl, val) 1007 1009 END DO … … 1016 1018 !------------------------------------------------------------------------------------------------------------------------------ 1017 1019 CHARACTER(LEN=*), INTENT(IN) :: key, val 1018 TYPE(k ys),INTENT(INOUT) :: ky1020 TYPE(keys_type), INTENT(INOUT) :: ky 1019 1021 LOGICAL, OPTIONAL, INTENT(IN) :: lOverWrite 1020 CHARACTER(LEN= 256),ALLOCATABLE :: k(:), v(:)1022 CHARACTER(LEN=maxlen), ALLOCATABLE :: k(:), v(:) 1021 1023 INTEGER :: iky, nky 1022 1024 LOGICAL :: lo … … 1037 1039 !------------------------------------------------------------------------------------------------------------------------------ 1038 1040 CHARACTER(LEN=*), INTENT(IN) :: key, val 1039 TYPE(k ys),INTENT(INOUT) :: ky(:)1041 TYPE(keys_type), INTENT(INOUT) :: ky(:) 1040 1042 LOGICAL, OPTIONAL, INTENT(IN) :: lOverWrite 1041 1043 INTEGER :: itr … … 1050 1052 ! Purpose: The values of the keys of the tracer named "tr0" are overwritten by the values found in the *.def files, if any. 1051 1053 !------------------------------------------------------------------------------------------------------------------------------ 1052 TYPE(tra ), ALLOCATABLE, INTENT(INOUT) :: t(:)1053 CHARACTER(LEN=*), INTENT(IN) :: tr01054 CHARACTER(LEN= 256) :: val1055 INTEGER :: ik, jd1054 TYPE(trac_type), ALLOCATABLE, INTENT(INOUT) :: t(:) 1055 CHARACTER(LEN=*), INTENT(IN) :: tr0 1056 CHARACTER(LEN=maxlen) :: val 1057 INTEGER :: ik, jd 1056 1058 jd = strIdx(t%name, tr0) 1057 1059 IF(jd == 0) RETURN … … 1069 1071 INTEGER, INTENT(IN) :: itr 1070 1072 CHARACTER(LEN=*), INTENT(IN) :: keyn(:) 1071 TYPE(tra ),INTENT(INOUT) :: ky(:)1072 CHARACTER(LEN= 256), ALLOCATABLE :: k(:), v(:)1073 LOGICAL, ALLOCATABLE :: ll(:)1073 TYPE(trac_type), INTENT(INOUT) :: ky(:) 1074 CHARACTER(LEN=maxlen), ALLOCATABLE :: k(:), v(:) 1075 LOGICAL, ALLOCATABLE :: ll(:) 1074 1076 INTEGER :: iky 1075 1077 !------------------------------------------------------------------------------------------------------------------------------ … … 1086 1088 !------------------------------------------------------------------------------------------------------------------------------ 1087 1089 CHARACTER(LEN=*), INTENT(IN) :: keyn(:) 1088 TYPE(tra ),INTENT(INOUT) :: ky(:)1090 TYPE(trac_type), INTENT(INOUT) :: ky(:) 1089 1091 INTEGER :: iky 1090 1092 !------------------------------------------------------------------------------------------------------------------------------ … … 1100 1102 !============================================================================================================================== 1101 1103 SUBROUTINE getKey_init(tracers_, isotopes_) 1102 TYPE(tra ), OPTIONAL, INTENT(IN) :: tracers_(:)1103 TYPE(iso ), OPTIONAL, INTENT(IN) :: isotopes_(:)1104 TYPE(trac_type), OPTIONAL, INTENT(IN) :: tracers_(:) 1105 TYPE(isot_type), OPTIONAL, INTENT(IN) :: isotopes_(:) 1104 1106 IF(PRESENT( tracers_)) tracers = tracers_ 1105 1107 IF(PRESENT(isotopes_)) isotopes = isotopes_ 1106 1108 END SUBROUTINE getKey_init 1107 1109 !============================================================================================================================== 1108 CHARACTER(LEN= 256) FUNCTION fgetKey(itr, keyn, ky, def_val) RESULT(out)1110 CHARACTER(LEN=maxlen) FUNCTION fgetKey(itr, keyn, ky, def_val) RESULT(out) 1109 1111 !------------------------------------------------------------------------------------------------------------------------------ 1110 1112 ! Purpose: Internal function ; get a key value in string format (this is the returned argument). … … 1112 1114 INTEGER, INTENT(IN) :: itr 1113 1115 CHARACTER(LEN=*), INTENT(IN) :: keyn 1114 TYPE(k ys),INTENT(IN) :: ky(:)1116 TYPE(keys_type), INTENT(IN) :: ky(:) 1115 1117 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: def_val 1116 1118 !------------------------------------------------------------------------------------------------------------------------------ … … 1126 1128 ! * "ky" specified: try in "ky" for "tnam" with phase and tagging suffixes, then without. 1127 1129 ! The returned error code is always .FALSE.: an empty string is returned when the key hasn't been found. 1128 CHARACTER(LEN=*), INTENT(IN) :: keyn1129 CHARACTER(LEN= 256),INTENT(OUT) :: val1130 CHARACTER(LEN=*), INTENT(IN) :: tname1131 TYPE(k ys), OPTIONAL, INTENT(IN) :: ky(:)1130 CHARACTER(LEN=*), INTENT(IN) :: keyn 1131 CHARACTER(LEN=maxlen), INTENT(OUT) :: val 1132 CHARACTER(LEN=*), INTENT(IN) :: tname 1133 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1132 1134 INTEGER :: is 1133 1135 lerr = .FALSE. … … 1147 1149 1148 1150 FUNCTION getKeyByName_prv(keyn, tname, ky) RESULT(val) 1149 CHARACTER(LEN= 256):: val1151 CHARACTER(LEN=maxlen) :: val 1150 1152 CHARACTER(LEN=*), INTENT(IN) :: keyn 1151 1153 CHARACTER(LEN=*), INTENT(IN) :: tname 1152 TYPE(k ys),INTENT(IN) :: ky(:)1154 TYPE(keys_type), INTENT(IN) :: ky(:) 1153 1155 INTEGER :: itr, iky 1154 1156 val = ''; iky = 0 … … 1162 1164 LOGICAL FUNCTION getKeyByName_sm(keyn, val, tnam, ky) RESULT(lerr) 1163 1165 CHARACTER(LEN=*), INTENT(IN) :: keyn 1164 CHARACTER(LEN= 256),ALLOCATABLE, INTENT(OUT) :: val(:)1166 CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) :: val(:) 1165 1167 CHARACTER(LEN=*), TARGET, OPTIONAL, INTENT(IN) :: tnam(:) 1166 TYPE(k ys),TARGET, OPTIONAL, INTENT(IN) :: ky(:)1167 CHARACTER(LEN= 256),POINTER :: n(:)1168 TYPE(keys_type), TARGET, OPTIONAL, INTENT(IN) :: ky(:) 1169 CHARACTER(LEN=maxlen), POINTER :: n(:) 1168 1170 INTEGER :: iq 1169 1171 n => tracers(:)%keys%name; IF(PRESENT(tnam)) n => tnam(:) … … 1174 1176 !============================================================================================================================== 1175 1177 LOGICAL FUNCTION getKeyByName_i1(keyn, val, tnam, ky) RESULT(lerr) 1176 CHARACTER(LEN=*), INTENT(IN) :: keyn1177 INTEGER, INTENT(OUT) :: val1178 CHARACTER(LEN=*), INTENT(IN) :: tnam1179 TYPE(k ys), OPTIONAL, INTENT(IN) :: ky(:)1180 CHARACTER(LEN= 256) :: sval1178 CHARACTER(LEN=*), INTENT(IN) :: keyn 1179 INTEGER, INTENT(OUT) :: val 1180 CHARACTER(LEN=*), INTENT(IN) :: tnam 1181 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1182 CHARACTER(LEN=maxlen) :: sval 1181 1183 INTEGER :: ierr 1182 1184 IF( PRESENT(ky)) lerr = getKeyByName_s1(keyn, sval, tnam, ky) 1183 1185 IF(.NOT.PRESENT(ky)) lerr = getKeyByName_s1(keyn, sval, tnam) 1184 IF(test(fmsg( lerr, 'key "'//TRIM(keyn)//'" or tracer "'//TRIM(tnam)//'" is missing'),lerr)) RETURN1186 IF(test(fmsg('key "'//TRIM(keyn)//'" or tracer "'//TRIM(tnam)//'" is missing', modname, lerr), lerr)) RETURN 1185 1187 READ(sval, *, IOSTAT=ierr) val 1186 IF(test(fmsg( ierr/=0,'key "'//TRIM(keyn)//'" of tracer "'//TRIM(tnam)//'" is not an integer'), lerr)) RETURN1188 IF(test(fmsg('key "'//TRIM(keyn)//'" of tracer "'//TRIM(tnam)//'" is not an integer', modname, lerr), lerr)) RETURN 1187 1189 END FUNCTION getKeyByName_i1 1188 1190 !============================================================================================================================== … … 1191 1193 INTEGER, ALLOCATABLE, INTENT(OUT) :: val(:) 1192 1194 CHARACTER(LEN=*), TARGET, OPTIONAL, INTENT(IN) :: tnam(:) 1193 TYPE(k ys),TARGET, OPTIONAL, INTENT(IN) :: ky(:)1194 CHARACTER(LEN= 256), POINTER :: n(:)1195 TYPE(keys_type), TARGET, OPTIONAL, INTENT(IN) :: ky(:) 1196 CHARACTER(LEN=maxlen), POINTER :: n(:) 1195 1197 INTEGER :: iq 1196 1198 n => tracers(:)%name; IF(PRESENT(tnam)) n => tnam(:) … … 1201 1203 !============================================================================================================================== 1202 1204 LOGICAL FUNCTION getKeyByName_r1(keyn, val, tnam, ky) RESULT(lerr) 1203 CHARACTER(LEN=*), INTENT(IN) :: keyn1204 REAL, INTENT(OUT) :: val1205 CHARACTER(LEN=*), INTENT(IN) :: tnam1206 TYPE(k ys), OPTIONAL, INTENT(IN) :: ky(:)1207 CHARACTER(LEN= 256) :: sval1205 CHARACTER(LEN=*), INTENT(IN) :: keyn 1206 REAL, INTENT(OUT) :: val 1207 CHARACTER(LEN=*), INTENT(IN) :: tnam 1208 TYPE(keys_type), OPTIONAL, INTENT(IN) :: ky(:) 1209 CHARACTER(LEN=maxlen) :: sval 1208 1210 INTEGER :: ierr 1209 1211 IF( PRESENT(ky)) lerr = getKeyByName_s1(keyn, sval, tnam, ky) 1210 1212 IF(.NOT.PRESENT(ky)) lerr = getKeyByName_s1(keyn, sval, tnam) 1211 IF(test(fmsg( lerr, 'key "'//TRIM(keyn)//'" or tracer "'//TRIM(tnam)//'" is missing'),lerr)) RETURN1213 IF(test(fmsg('key "'//TRIM(keyn)//'" or tracer "'//TRIM(tnam)//'" is missing', modname, lerr), lerr)) RETURN 1212 1214 READ(sval, *, IOSTAT=ierr) val 1213 IF(test(fmsg( ierr/=0,'key "'//TRIM(keyn)//'" of tracer "'//TRIM(tnam)//'" is not a real'), lerr)) RETURN1215 IF(test(fmsg('key "'//TRIM(keyn)//'" of tracer "'//TRIM(tnam)//'" is not a real', modname, lerr), lerr)) RETURN 1214 1216 END FUNCTION getKeyByName_r1 1215 1217 !============================================================================================================================== … … 1218 1220 REAL, ALLOCATABLE, INTENT(OUT) :: val(:) 1219 1221 CHARACTER(LEN=*), TARGET, OPTIONAL, INTENT(IN) :: tnam(:) 1220 TYPE(k ys),TARGET, OPTIONAL, INTENT(IN) :: ky(:)1221 CHARACTER(LEN= 256), POINTER :: n(:)1222 TYPE(keys_type), TARGET, OPTIONAL, INTENT(IN) :: ky(:) 1223 CHARACTER(LEN=maxlen), POINTER :: n(:) 1222 1224 INTEGER :: iq 1223 1225 n => tracers(:)%name; IF(PRESENT(tnam)) n => tnam(:) … … 1232 1234 !=== REMOVE, IF ANY, OR ADD THE PHASE SUFFIX OF THE TRACER NAMED "s" ========================================================== 1233 1235 !============================================================================================================================== 1234 ELEMENTAL CHARACTER(LEN= 256) FUNCTION delPhase(s) RESULT(out)1236 ELEMENTAL CHARACTER(LEN=maxlen) FUNCTION delPhase(s) RESULT(out) 1235 1237 CHARACTER(LEN=*), INTENT(IN) :: s 1236 1238 INTEGER :: l, i, ix … … 1249 1251 END FUNCTION delPhase 1250 1252 !------------------------------------------------------------------------------------------------------------------------------ 1251 CHARACTER(LEN= 256) FUNCTION addPhase_1(s,pha) RESULT(out)1253 CHARACTER(LEN=maxlen) FUNCTION addPhase_1(s,pha) RESULT(out) 1252 1254 CHARACTER(LEN=*), INTENT(IN) :: s 1253 1255 CHARACTER(LEN=1), INTENT(IN) :: pha … … 1262 1264 !------------------------------------------------------------------------------------------------------------------------------ 1263 1265 FUNCTION addPhase_m(s,pha) RESULT(out) 1264 CHARACTER(LEN=*), INTENT(IN):: s(:)1265 CHARACTER(LEN=1), INTENT(IN):: pha1266 CHARACTER(LEN= 256), ALLOCATABLE :: out(:)1266 CHARACTER(LEN=*), INTENT(IN) :: s(:) 1267 CHARACTER(LEN=1), INTENT(IN) :: pha 1268 CHARACTER(LEN=maxlen), ALLOCATABLE :: out(:) 1267 1269 INTEGER :: k 1268 1270 out = [( addPhase_1(s(k), pha), k=1, SIZE(s) )] … … 1274 1276 !=== GET THE NAME(S) OF THE ANCESTOR(S) OF TRACER(S) "tname" AT GENERATION "igen" IN THE TRACERS DESCRIPTORS LIST "tr" ======= 1275 1277 !============================================================================================================================== 1276 CHARACTER(LEN= 256) FUNCTION ancestor_1(t, tname, igen) RESULT(out)1277 TYPE(tra ),INTENT(IN) :: t(:)1278 CHARACTER(LEN=maxlen) FUNCTION ancestor_1(t, tname, igen) RESULT(out) 1279 TYPE(trac_type), INTENT(IN) :: t(:) 1278 1280 CHARACTER(LEN=*), INTENT(IN) :: tname 1279 1281 INTEGER, OPTIONAL, INTENT(IN) :: igen … … 1285 1287 !------------------------------------------------------------------------------------------------------------------------------ 1286 1288 FUNCTION ancestor_m(t, tname, igen) RESULT(out) 1287 CHARACTER(LEN= 256), ALLOCATABLE:: out(:)1288 TYPE(tra ),INTENT(IN) :: t(:)1289 CHARACTER(LEN=maxlen), ALLOCATABLE :: out(:) 1290 TYPE(trac_type), INTENT(IN) :: t(:) 1289 1291 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: tname(:) 1290 1292 INTEGER, OPTIONAL, INTENT(IN) :: igen … … 1305 1307 INTEGER FUNCTION idxAncestor_1(t, tname, igen) RESULT(out) 1306 1308 ! Return the name of the generation "igen" ancestor of "tname" 1307 TYPE(tra ),INTENT(IN) :: t(:)1309 TYPE(trac_type), INTENT(IN) :: t(:) 1308 1310 CHARACTER(LEN=*), INTENT(IN) :: tname 1309 1311 INTEGER, OPTIONAL, INTENT(IN) :: igen … … 1312 1314 out = strIdx(t(:)%name, tname) 1313 1315 IF(out == 0) RETURN 1314 IF(t(out)%i gen <= ig) RETURN1315 DO WHILE(t(out)%i gen > ig); out = strIdx(t(:)%name, t(out)%prnt); END DO1316 IF(t(out)%iGeneration <= ig) RETURN 1317 DO WHILE(t(out)%iGeneration > ig); out = strIdx(t(:)%name, t(out)%parent); END DO 1316 1318 END FUNCTION idxAncestor_1 1317 1319 !------------------------------------------------------------------------------------------------------------------------------ 1318 1320 FUNCTION idxAncestor_m(t, tname, igen) RESULT(out) 1319 1321 INTEGER, ALLOCATABLE :: out(:) 1320 TYPE(tra ),INTENT(IN) :: t(:)1322 TYPE(trac_type), INTENT(IN) :: t(:) 1321 1323 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: tname(:) 1322 1324 INTEGER, OPTIONAL, INTENT(IN) :: igen -
strings_mod.F90
r1 r2 4 4 5 5 PRIVATE 6 PUBLIC :: m odname, init_printout, msg, fmsg, get_in, lunout, prt_level6 PUBLIC :: maxlen, init_printout, msg, fmsg, get_in, lunout, prt_level 7 7 PUBLIC :: strLower, strHead, strStack, strClean, strIdx, strCount, strReplace 8 8 PUBLIC :: strUpper, strTail, strStackm, strReduce, strFind, strParse, cat, find … … 13 13 14 14 INTERFACE get_in; MODULE PROCEDURE getin_s, getin_i, getin_r, getin_l; END INTERFACE get_in 15 INTERFACE msg; MODULE PROCEDURE msg_1, msg_l1,msg_m; END INTERFACE msg16 INTERFACE fmsg; MODULE PROCEDURE fmsg_1, fmsg_l1,fmsg_m; END INTERFACE fmsg15 INTERFACE msg; MODULE PROCEDURE msg_1, msg_m; END INTERFACE msg 16 INTERFACE fmsg; MODULE PROCEDURE fmsg_1, fmsg_m; END INTERFACE fmsg 17 17 INTERFACE strHead; MODULE PROCEDURE strHead_1, strHead_m; END INTERFACE strHead 18 18 INTERFACE strTail; MODULE PROCEDURE strTail_1, strTail_m; END INTERFACE strTail … … 32 32 INTERFACE testFile; MODULE PROCEDURE testFile_1, testFile_m; END INTERFACE testFile 33 33 34 CHARACTER(LEN=256), SAVE :: modname = '' !--- Current subroutine name 35 INTEGER, SAVE :: lunout = 6 !--- Printing unit (default: 6, ie. on screen) 36 INTEGER, SAVE :: prt_level = 1 !--- Printing level (default: 1, ie. print all) 37 34 INTEGER, PARAMETER :: maxlen = 256 !--- Standard maximum length for strings 35 INTEGER, SAVE :: lunout = 6 !--- Printing unit (default: 6, ie. on screen) 36 INTEGER, SAVE :: prt_level = 1 !--- Printing level (default: 1, ie. print all) 38 37 39 38 CONTAINS … … 57 56 !============================================================================================================================== 58 57 SUBROUTINE getin_s(nam, val, def) 59 USE ioipsl_getin _mod, ONLY: getin58 USE ioipsl_getincom, ONLY: getin 60 59 CHARACTER(LEN=*), INTENT(IN) :: nam 61 60 CHARACTER(LEN=*), INTENT(INOUT) :: val … … 66 65 !============================================================================================================================== 67 66 SUBROUTINE getin_i(nam, val, def) 68 USE ioipsl_getin _mod, ONLY: getin67 USE ioipsl_getincom, ONLY: getin 69 68 CHARACTER(LEN=*), INTENT(IN) :: nam 70 69 INTEGER, INTENT(INOUT) :: val … … 75 74 !============================================================================================================================== 76 75 SUBROUTINE getin_r(nam, val, def) 77 USE ioipsl_getin _mod, ONLY: getin76 USE ioipsl_getincom, ONLY: getin 78 77 CHARACTER(LEN=*), INTENT(IN) :: nam 79 78 REAL, INTENT(INOUT) :: val … … 84 83 !============================================================================================================================== 85 84 SUBROUTINE getin_l(nam, val, def) 86 USE ioipsl_getin _mod, ONLY: getin85 USE ioipsl_getincom, ONLY: getin 87 86 CHARACTER(LEN=*), INTENT(IN) :: nam 88 87 LOGICAL, INTENT(INOUT) :: val … … 97 96 !=== Display one or several messages, one each line, starting with the current routine name "modname". 98 97 !============================================================================================================================== 99 SUBROUTINE msg_1(str, unit) 100 CHARACTER(LEN=*), INTENT(IN) :: str 101 INTEGER, OPTIONAL, INTENT(IN) :: unit 98 SUBROUTINE msg_1(str, modname, ll, unit) 99 !--- Display a simple message "str". Optional parameters: 100 ! * "modname": module name, displayed in front of the message (with ": " separator) if present. 101 ! * "ll": message trigger ; message is displayed only if ll==.TRUE. 102 ! * "unit": write unit (by default: "lunout") 103 CHARACTER(LEN=*), INTENT(IN) :: str 104 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: modname 105 LOGICAL, OPTIONAL, INTENT(IN) :: ll 106 INTEGER, OPTIONAL, INTENT(IN) :: unit 102 107 INTEGER :: unt 108 IF(PRESENT(ll)) THEN; IF(ll) RETURN; END IF 103 109 unt = lunout; IF(PRESENT(unit)) unt = unit 104 WRITE(unt,'(a)') TRIM(modname)//': '//str 110 IF(PRESENT(modname)) THEN 111 WRITE(unt,'(a)') TRIM(modname)//': '//str !--- Routine name provided 112 ELSE 113 WRITE(unt,'(a)') str !--- Simple message 114 END IF 105 115 END SUBROUTINE msg_1 106 116 !============================================================================================================================== 107 SUBROUTINE msg_l1(ll, str, unit) 108 LOGICAL, INTENT(IN) :: ll 109 CHARACTER(LEN=*), INTENT(IN) :: str 110 INTEGER, OPTIONAL, INTENT(IN) :: unit 111 INTEGER :: unt 112 IF(.NOT.ll) RETURN 113 unt = lunout; IF(PRESENT(unit)) unt = unit 114 WRITE(unt,'(a)') TRIM(modname)//': '//str 115 END SUBROUTINE msg_l1 116 !============================================================================================================================== 117 SUBROUTINE msg_m(str, unit, nmax) 118 CHARACTER(LEN=*), INTENT(IN) :: str(:) 119 INTEGER, OPTIONAL, INTENT(IN) :: unit 120 INTEGER, OPTIONAL, INTENT(IN) :: nmax 121 CHARACTER(LEN=256), ALLOCATABLE :: s(:) 117 SUBROUTINE msg_m(str, modname, ll, unit, nmax) 118 !--- Same as msg_1 with multiple strings that are stacked (separator: coma) on up to "nmax" full lines. 119 CHARACTER(LEN=*), INTENT(IN) :: str(:) 120 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: modname 121 LOGICAL, OPTIONAL, INTENT(IN) :: ll 122 INTEGER, OPTIONAL, INTENT(IN) :: unit 123 INTEGER, OPTIONAL, INTENT(IN) :: nmax 124 CHARACTER(LEN=maxlen), ALLOCATABLE :: s(:) 122 125 INTEGER :: unt, nmx, k 126 LOGICAL :: lerr 127 lerr = .TRUE.; IF(PRESENT(ll)) lerr = ll 123 128 unt = lunout ; IF(PRESENT(unit)) unt = unit 124 129 nmx = 128; IF(PRESENT(nmax)) nmx = nmax 125 130 s = strStackm(str, ', ', nmx) 126 DO k=1,SIZE(s); WRITE(unt,'(a)') TRIM(modname)//': '//TRIM(s(k)); END DO 131 IF(PRESENT(modname)) THEN 132 DO k=1,SIZE(s); CALL msg_1(s(k), modname, lerr, unt); END DO 133 ELSE 134 DO k=1,SIZE(s); CALL msg_1(s(k), ll=lerr, unit=unt); END DO 135 END IF 127 136 END SUBROUTINE msg_m 128 137 !============================================================================================================================== 129 LOGICAL FUNCTION fmsg_1(str, unit) RESULT(lerr) 130 CHARACTER(LEN=*), INTENT(IN) :: str 131 INTEGER, OPTIONAL, INTENT(IN) :: unit 138 LOGICAL FUNCTION fmsg_1(str, modname, ll, unit) RESULT(lerr) 139 CHARACTER(LEN=*), INTENT(IN) :: str 140 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: modname 141 LOGICAL, OPTIONAL, INTENT(IN) :: ll 142 INTEGER, OPTIONAL, INTENT(IN) :: unit 132 143 INTEGER :: unt 133 lerr = .TRUE. 144 lerr = .TRUE.; IF(PRESENT(ll)) lerr = ll 134 145 unt = lunout ; IF(PRESENT(unit)) unt = unit 135 CALL msg_1(str, unt) 146 IF(PRESENT(modname)) THEN 147 CALL msg_1(str, modname, lerr, unt) 148 ELSE 149 CALL msg_1(str, ll=lerr, unit=unt) 150 END IF 136 151 END FUNCTION fmsg_1 137 152 !============================================================================================================================== 138 LOGICAL FUNCTION fmsg_l1(li, str, unit) RESULT(lerr) 139 LOGICAL, INTENT(IN) :: li 140 CHARACTER(LEN=*), INTENT(IN) :: str 141 INTEGER, OPTIONAL, INTENT(IN) :: unit 142 INTEGER :: unt 143 lerr = li; IF(.NOT.lerr) RETURN 144 unt = lunout ; IF(PRESENT(unit)) unt = unit 145 CALL msg_l1(lerr, str, unt) 146 END FUNCTION fmsg_l1 147 !============================================================================================================================== 148 LOGICAL FUNCTION fmsg_m(str, unit, nmax) RESULT(lerr) 149 CHARACTER(LEN=*), INTENT(IN) :: str(:) 150 INTEGER, OPTIONAL, INTENT(IN) :: unit 151 INTEGER, OPTIONAL, INTENT(IN) :: nmax 153 LOGICAL FUNCTION fmsg_m(str, modname, ll, unit, nmax) RESULT(lerr) 154 CHARACTER(LEN=*), INTENT(IN) :: str(:) 155 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: modname 156 LOGICAL, OPTIONAL, INTENT(IN) :: ll 157 INTEGER, OPTIONAL, INTENT(IN) :: unit 158 INTEGER, OPTIONAL, INTENT(IN) :: nmax 152 159 INTEGER :: unt, nmx 153 lerr = .TRUE. 160 lerr = .TRUE.; IF(PRESENT(ll)) lerr = ll 154 161 unt = lunout ; IF(PRESENT(unit)) unt = unit 155 162 nmx = 128; IF(PRESENT(nmax)) nmx = nmax 156 CALL msg_m(str, unt, nmx) 163 IF(PRESENT(modname)) THEN 164 CALL msg_m(str, modname, lerr, unt, nmx) 165 ELSE 166 CALL msg_m(str, ll=lerr, unit=unt, nmax=nmx) 167 END IF 157 168 END FUNCTION fmsg_m 158 169 !============================================================================================================================== … … 162 173 !=== Lower/upper case conversion function. ==================================================================================== 163 174 !============================================================================================================================== 164 ELEMENTAL CHARACTER(LEN= 256) FUNCTION strLower(str) RESULT(out)175 ELEMENTAL CHARACTER(LEN=maxlen) FUNCTION strLower(str) RESULT(out) 165 176 CHARACTER(LEN=*), INTENT(IN) :: str 166 177 INTEGER :: k … … 171 182 END FUNCTION strLower 172 183 !============================================================================================================================== 173 ELEMENTAL CHARACTER(LEN= 256) FUNCTION strUpper(str) RESULT(out)184 ELEMENTAL CHARACTER(LEN=maxlen) FUNCTION strUpper(str) RESULT(out) 174 185 CHARACTER(LEN=*), INTENT(IN) :: str 175 186 INTEGER :: k … … 188 199 !=== * strHead(..,.TRUE.) = 'a_b' ${str%$sep*} ================ 189 200 !============================================================================================================================== 190 CHARACTER(LEN= 256) FUNCTION strHead_1(str,sep,lFirst) RESULT(out)201 CHARACTER(LEN=maxlen) FUNCTION strHead_1(str,sep,lFirst) RESULT(out) 191 202 CHARACTER(LEN=*), INTENT(IN) :: str 192 203 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep … … 203 214 !============================================================================================================================== 204 215 FUNCTION strHead_m(str,sep,lFirst) RESULT(out) 205 CHARACTER(LEN= 256),ALLOCATABLE :: out(:)216 CHARACTER(LEN=maxlen), ALLOCATABLE :: out(:) 206 217 CHARACTER(LEN=*), INTENT(IN) :: str(:) 207 218 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep … … 222 233 !=== * strHead(..,.TRUE.) = 'c' ${str##*$sep} ================ 223 234 !============================================================================================================================== 224 CHARACTER(LEN= 256) FUNCTION strTail_1(str,sep,lFirst) RESULT(out)235 CHARACTER(LEN=maxlen) FUNCTION strTail_1(str,sep,lFirst) RESULT(out) 225 236 CHARACTER(LEN=*), INTENT(IN) :: str 226 237 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep … … 237 248 !============================================================================================================================== 238 249 FUNCTION strTail_m(str,sep,lFirst) RESULT(out) 239 CHARACTER(LEN= 256),ALLOCATABLE :: out(:)250 CHARACTER(LEN=maxlen), ALLOCATABLE :: out(:) 240 251 CHARACTER(LEN=*), INTENT(IN) :: str(:) 241 252 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep … … 270 281 !============================================================================================================================== 271 282 FUNCTION strStackm(str, sep, nmax) RESULT(out) 272 CHARACTER(LEN= 256),ALLOCATABLE :: out(:)283 CHARACTER(LEN=maxlen), ALLOCATABLE :: out(:) 273 284 CHARACTER(LEN=*), INTENT(IN) :: str(:) 274 285 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: sep 275 286 INTEGER, OPTIONAL, INTENT(IN) :: nmax 276 CHARACTER(LEN= 256), ALLOCATABLE :: t(:)277 CHARACTER(LEN= 256) :: sp287 CHARACTER(LEN=maxlen), ALLOCATABLE :: t(:) 288 CHARACTER(LEN=maxlen) :: sp 278 289 INTEGER :: is, ns, no, mx, n 279 290 IF(SIZE(str) == 0) THEN; out = ['']; RETURN; END IF … … 328 339 CHARACTER(LEN=*), ALLOCATABLE, INTENT(INOUT) :: str1(:) 329 340 INTEGER, OPTIONAL, INTENT(OUT) :: nb 330 CHARACTER(LEN= 256), ALLOCATABLE :: s1(:)341 CHARACTER(LEN=maxlen), ALLOCATABLE :: s1(:) 331 342 INTEGER :: k, n, n1 332 343 IF(PRESENT(nb)) nb = 0 … … 342 353 CHARACTER(LEN=*), ALLOCATABLE, INTENT(INOUT) :: str1(:) 343 354 CHARACTER(LEN=*), INTENT(IN) :: str2(:) 344 CHARACTER(LEN= 256), ALLOCATABLE :: s1(:), s2(:)355 CHARACTER(LEN=maxlen), ALLOCATABLE :: s1(:), s2(:) 345 356 INTEGER :: k 346 357 IF(SIZE(str2)==0) RETURN … … 432 443 LOGICAL, OPTIONAL, INTENT(IN) :: lSc !--- Care about nbs with front sign or in scient. notation 433 444 434 INTEGER :: idx0!--- Used to display an identified non-numeric string435 INTEGER, ALLOCATABLE :: ii(:)436 LOGICAL :: ll, ls437 CHARACTER(LEN= 256):: d445 INTEGER :: idx0 !--- Used to display an identified non-numeric string 446 INTEGER, ALLOCATABLE :: ii(:) 447 LOGICAL :: ll, ls 448 CHARACTER(LEN=maxlen) :: d 438 449 ! modname = 'strIdx' 439 450 lerr = .FALSE. … … 545 556 DO 546 557 lerr = strIdx_prv(r, delimiter, ib, ie, jd, ll) 547 IF(fmsg( lerr,'"'//TRIM(r(ib:ie-1))//'" is not numeric')) RETURN558 IF(fmsg('"'//TRIM(r(ib:ie-1))//'" is not numeric', ll=lerr)) RETURN 548 559 IF(jd == 0) EXIT 549 560 ib = ie + LEN(delimiter(jd)) … … 560 571 !============================================================================================================================== 561 572 LOGICAL FUNCTION strParse_1(rawList, delimiter, keys, lSc, vals, n) RESULT(lerr) 562 CHARACTER(LEN=*), INTENT(IN) :: rawList, delimiter563 CHARACTER(LEN= 256), ALLOCATABLE, INTENT(OUT) :: keys(:)564 LOGICAL, OPTIONAL, INTENT(IN) :: lSc !--- Take care about numbers in scientific notation565 CHARACTER(LEN= 256), ALLOCATABLE, OPTIONAL, INTENT(OUT) :: vals(:)566 INTEGER, OPTIONAL, INTENT(OUT) :: n573 CHARACTER(LEN=*), INTENT(IN) :: rawList, delimiter 574 CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) :: keys(:) 575 LOGICAL, OPTIONAL, INTENT(IN) :: lSc !--- Take care about numbers in scientific notation 576 CHARACTER(LEN=maxlen), ALLOCATABLE, OPTIONAL, INTENT(OUT) :: vals(:) 577 INTEGER, OPTIONAL, INTENT(OUT) :: n 567 578 LOGICAL :: ll 568 579 ! modname = 'strParse' … … 574 585 !============================================================================================================================== 575 586 LOGICAL FUNCTION strParse_m(rawList, delimiter, keys, lSc, vals, n, id) RESULT(lerr) 576 CHARACTER(LEN=*), INTENT(IN) :: rawList, delimiter(:)577 CHARACTER(LEN= 256), ALLOCATABLE, INTENT(OUT) :: keys(:) !--- Parsed keys vector578 LOGICAL, OPTIONAL, INTENT(IN) :: lSc !--- Take care about numbers in scientific notation579 CHARACTER(LEN= 256), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: vals(:) !--- Values for <name>=<value> keys580 INTEGER, OPTIONAL, INTENT(OUT) :: n !--- Length of the parsed vector581 INTEGER, OPTIONAL, ALLOCATABLE, INTENT(OUT) :: id(:) !--- Indexes of the separators in "delimiter(:)" vector587 CHARACTER(LEN=*), INTENT(IN) :: rawList, delimiter(:) 588 CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) :: keys(:) !--- Parsed keys vector 589 LOGICAL, OPTIONAL, INTENT(IN) :: lSc !--- Take care about numbers in scientific notation 590 CHARACTER(LEN=maxlen), OPTIONAL, ALLOCATABLE, INTENT(OUT) :: vals(:) !--- Values for <name>=<value> keys 591 INTEGER, OPTIONAL, INTENT(OUT) :: n !--- Length of the parsed vector 592 INTEGER, OPTIONAL, ALLOCATABLE, INTENT(OUT) :: id(:) !--- Indexes of the separators in "delimiter(:)" vector 582 593 583 594 CHARACTER(LEN=1024) :: r … … 587 598 ! modname = 'strParse' 588 599 ll = .FALSE.; IF(PRESENT(lSc)) ll = lSc 589 IF(test(fmsg( strCount_1m(rawList, delimiter, nk, ll), "Couldn't parse list: non-numerical strings were found"),lerr)) RETURN600 IF(test(fmsg("Couldn't parse list: non-numerical strings were found", ll=strCount_1m(rawList, delimiter, nk, ll)),lerr)) RETURN 590 601 591 602 !--- FEW ALLOCATIONS … … 600 611 ib = 1 601 612 DO ik = 1, nk-1 602 IF(test(fmsg( strIdx_prv(r, delimiter, ib, ie, jd, ll),'Non-numeric values found'),lerr)) RETURN613 IF(test(fmsg('Non-numeric values found', ll=strIdx_prv(r, delimiter, ib, ie, jd, ll)),lerr)) RETURN 603 614 keys(ik) = r(ib:ie-1) 604 615 IF(PRESENT(vals)) CALL parseKeys(keys(ik), vals(ik)) !--- Parse a <key>=<val> pair … … 674 685 CHARACTER(LEN=*), TARGET, INTENT(IN) :: s0 675 686 CHARACTER(LEN=*), OPTIONAL, TARGET, INTENT(IN) :: s1, s2, s3, s4, s5, s6, s7, s8, s9 676 CHARACTER(LEN= 256), ALLOCATABLE :: out(:)677 CHARACTER(LEN= 256), POINTER :: s687 CHARACTER(LEN=maxlen), ALLOCATABLE :: out(:) 688 CHARACTER(LEN=maxlen), POINTER :: s 678 689 LOGICAL :: lv(10) 679 690 INTEGER :: iv … … 693 704 CHARACTER(LEN=*), TARGET, DIMENSION(:), INTENT(IN) :: s0 694 705 CHARACTER(LEN=*), OPTIONAL, TARGET, DIMENSION(:), INTENT(IN) :: s1, s2, s3, s4, s5, s6, s7, s8, s9 695 CHARACTER(LEN= 256), ALLOCATABLE :: out(:,:)696 CHARACTER(LEN= 256), POINTER :: s(:)706 CHARACTER(LEN=maxlen), ALLOCATABLE :: out(:,:) 707 CHARACTER(LEN=maxlen), POINTER :: s(:) 697 708 LOGICAL :: lv(10) 698 709 INTEGER :: nrow, ncol, iv, n … … 707 718 END SELECT 708 719 n = SIZE(s, DIM=1) 709 IF(n/=nrow) THEN; CALL msg( 'Can''t concatenate vectors of differing lengths',1); STOP; END IF720 IF(n/=nrow) THEN; CALL msg("Can't concatenate vectors of differing lengths"); STOP; END IF 710 721 out(:,iv) = s(:) 711 722 END DO … … 748 759 END SELECT 749 760 n = SIZE(i, DIM=1) 750 IF(n/=nrow) THEN; CALL msg( 'Can''t concatenate vectors of differing lengths',1); STOP; END IF761 IF(n/=nrow) THEN; CALL msg("Can't concatenate vectors of differing lengths"); STOP; END IF 751 762 out(:,iv) = i(:) 752 763 END DO … … 789 800 END SELECT 790 801 n = SIZE(r, DIM=1) 791 IF(n/=nrow) THEN; CALL msg( 'Can''t concatenate vectors of differing lengths',1); STOP; END IF802 IF(n/=nrow) THEN; CALL msg("Can't concatenate vectors of differing lengths"); STOP; END IF 792 803 out(:,iv) = r(:) 793 804 END DO … … 830 841 END SELECT 831 842 n = SIZE(d, DIM=1) 832 IF(n/=nrow) THEN; CALL msg( 'Can''t concatenate vectors of differing lengths',1); STOP; END IF843 IF(n/=nrow) THEN; CALL msg("Can't concatenate vectors of differing lengths"); STOP; END IF 833 844 out(:,iv) = d(:) 834 845 END DO … … 852 863 853 864 CHARACTER(LEN=2048) :: row 854 CHARACTER(LEN= 256) :: rFm, el855 CHARACTER(LEN= 256), ALLOCATABLE :: d(:,:)865 CHARACTER(LEN=maxlen) :: rFm, el 866 CHARACTER(LEN=maxlen), ALLOCATABLE :: d(:,:) 856 867 CHARACTER(LEN=1) :: s1, sp 857 868 INTEGER :: is, ii, ir, np, nrow, unt, ic … … 870 881 871 882 !--- CHECK ARGUMENTS COHERENCE 872 lerr = np /= SIZE(titles); IF(fmsg( lerr, 'string "pattern" length and titles list mismatch')) RETURN883 lerr = np /= SIZE(titles); IF(fmsg('string "pattern" length and titles list mismatch', ll=lerr)) RETURN 873 884 IF(ls) THEN; ns = SIZE(s, DIM=1); ncol = ncol + SIZE(s, DIM=2) 874 885 lerr = COUNT([(p(ic:ic)=='s', ic=1, np)]) /= SIZE(s, DIM=2) … … 880 891 lerr = COUNT([(p(ic:ic)=='r', ic=1, np)]) /= SIZE(r, DIM=2) 881 892 END IF 882 883 IF(fmsg(lerr, 'string "pattern" length and arguments number mismatch')) RETURN 884 lerr = ncol /= SIZE(titles); IF(fmsg(lerr, '"titles" length and arguments number mismatch')) RETURN 885 lerr = ls.AND.li.AND.ns/=ni; IF(fmsg(lerr, 'string and integer arguments lengths mismatch')) RETURN 886 lerr = ls.AND.lr.AND.ns/=nr; IF(fmsg(lerr, 'string and real arguments lengths mismatch')) RETURN 887 lerr = li.AND.lr.AND.ni/=nr; IF(fmsg(lerr, 'integer and real arguments lengths mismatch')) RETURN 893 IF(fmsg('string "pattern" length and arguments number mismatch', ll=lerr)) RETURN 894 lerr = ncol /= SIZE(titles); IF(fmsg('"titles" length and arguments number mismatch', ll=lerr)) RETURN 895 lerr = ls.AND.li.AND.ns/=ni; IF(fmsg('string and integer arguments lengths mismatch', ll=lerr)) RETURN 896 lerr = ls.AND.lr.AND.ns/=nr; IF(fmsg( 'string and real arguments lengths mismatch', ll=lerr)) RETURN 897 lerr = li.AND.lr.AND.ni/=nr; IF(fmsg( 'integer and real arguments lengths mismatch', ll=lerr)) RETURN 888 898 nrow = MAX(ns,ni,nr)+1 889 899 nmx = nrow; IF(PRESENT(nmax)) nmx = MIN(nmx,nmax+1) … … 912 922 END DO 913 923 nr = LEN_TRIM(row)-1 !--- Final separator removed 914 CALL msg(row(1:nr), un t)924 CALL msg(row(1:nr), unit=unt) 915 925 IF(ir /= 1) CYCLE !--- Titles are underlined 916 926 row=''; DO ic=1,ncol; row=TRIM(row)//REPEAT('-',n(ic))//'+'; END DO 917 CALL msg(row(1:LEN_TRIM(row)-1), un t)927 CALL msg(row(1:LEN_TRIM(row)-1), unit=unt) 918 928 END DO 919 929 … … 932 942 LOGICAL, OPTIONAL, INTENT(IN) :: llast !--- Last variable: no final ',' 933 943 934 CHARACTER(LEN= 256) :: rFm, el935 CHARACTER(LEN= 256), ALLOCATABLE :: d(:,:)936 CHARACTER(LEN=:), ALLOCATABLE :: sp, row944 CHARACTER(LEN=maxlen) :: rFm, el 945 CHARACTER(LEN=maxlen), ALLOCATABLE :: d(:,:) 946 CHARACTER(LEN=:), ALLOCATABLE :: sp, row 937 947 INTEGER :: is, ii, ir, nrow, ic 938 948 INTEGER :: ns, ni, nr, ncol, np … … 957 967 lerr = COUNT([(p(ic:ic)=='r', ic=1, np)]) /= SIZE(r, DIM=2) 958 968 END IF 959 IF(fmsg( lerr, 'string "pattern" length and arguments number mismatch')) RETURN960 lerr = ncol /= SIZE(titles); IF(fmsg( lerr, '"titles" length and arguments number mismatch')) RETURN961 lerr = ls.AND.li.AND.ns/=ni; IF(fmsg( lerr, 'string and integer arguments lengths mismatch')) RETURN962 lerr = ls.AND.lr.AND.ns/=nr; IF(fmsg( lerr, 'string and real arguments lengths mismatch')) RETURN963 lerr = li.AND.lr.AND.ni/=nr; IF(fmsg( lerr, 'integer and real arguments lengths mismatch')) RETURN969 IF(fmsg('string "pattern" length and arguments number mismatch', ll=lerr)) RETURN 970 lerr = ncol /= SIZE(titles); IF(fmsg('"titles" length and arguments number mismatch', ll=lerr)) RETURN 971 lerr = ls.AND.li.AND.ns/=ni; IF(fmsg('string and integer arguments lengths mismatch', ll=lerr)) RETURN 972 lerr = ls.AND.lr.AND.ns/=nr; IF(fmsg( 'string and real arguments lengths mismatch', ll=lerr)) RETURN 973 lerr = li.AND.lr.AND.ni/=nr; IF(fmsg( 'integer and real arguments lengths mismatch', ll=lerr)) RETURN 964 974 965 975 !--- Allocate the assembled quantities array … … 1012 1022 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: err_msg, nam(:), subn !--- Error message, variables and calling subroutine names 1013 1023 INTEGER, OPTIONAL, INTENT(IN) :: nmax, unit !--- Maximum number of lines to display (default: all) 1014 CHARACTER(LEN= 256),ALLOCATABLE :: ttl(:)1024 CHARACTER(LEN=maxlen), ALLOCATABLE :: ttl(:) 1015 1025 LOGICAL, ALLOCATABLE :: m(:) 1016 1026 INTEGER, ALLOCATABLE :: ki(:), kj(:) 1017 1027 INTEGER :: i, j, k, rk, rk1, ib, ie, itr, nm, unt, nmx, nv 1018 CHARACTER(LEN= 256):: mes, sub, fm='(f12.9)', v, s1019 CHARACTER(LEN= 256),ALLOCATABLE :: vnm(:)1028 CHARACTER(LEN=maxlen) :: mes, sub, fm='(f12.9)', v, s 1029 CHARACTER(LEN=maxlen), ALLOCATABLE :: vnm(:) 1020 1030 1021 1031 lerr = ANY(ll); IF(.NOT.lerr) RETURN !--- No outliers -> finished … … 1028 1038 1029 1039 rk = SIZE(n); nv = SIZE(vnm) 1030 IF(test(fmsg(nv /= 1 .AND. nv /= n(rk), 'In "'//TRIM(sub)//'": SIZE(nam) /= 1 or =last "n" element' , unt),lerr)) RETURN 1031 IF(test(fmsg(SIZE(a) /= SIZE(ll), 'In "'//TRIM(sub)//'": "ll" and "a" sizes mismatch' , unt),lerr)) RETURN 1032 IF(test(fmsg(SIZE(a) /= PRODUCT(n), 'In "'//TRIM(sub)//'": profile "n" does not match "a" and "ll"', unt),lerr)) RETURN 1033 1034 WRITE(unt,*)'Outliers detected by '//TRIM(sub)//': '//TRIM(mes) 1040 IF(test(fmsg('SIZE(nam) /= 1 and /= last "n" element', sub, nv /= 1 .AND. nv /= n(rk), unt),lerr)) RETURN 1041 IF(test(fmsg('ll" and "a" sizes mismatch', sub, SIZE(a) /= SIZE(ll), unt),lerr)) RETURN 1042 IF(test(fmsg('profile "n" does not match "a" and "ll', sub, SIZE(a) /= PRODUCT(n), unt),lerr)) RETURN 1043 CALL msg(mes, sub, unit=unt) 1035 1044 1036 1045 !--- SCALAR CASE: single value to display … … 1051 1060 IF(nv == 1) lerr = dispTable('sr', ttl, s=cat(PACK(nam,ll)), r=cat(PACK(a,ll)), rFmt=fm, nmax=nmax) 1052 1061 IF(nv /= 1) lerr = dispTable('ir', ['name ','value'], i=cat(PACK(ki,m)), r=cat(PACK(a,ll)), rFmt=fm, nmax=nmax) 1053 CALL msg( lerr,'In '//TRIM(sub)//": can't display outliers table", unt)1062 CALL msg("can't display outliers table", sub, lerr, unt) 1054 1063 RETURN 1055 1064 END IF … … 1068 1077 IF(rk==2) lerr = dispTable('ir', ttl, i=cat(PACK(ki,m)), r=cat(PACK(a(ib:ie),m)), rFmt=fm, nmax=nmax) 1069 1078 IF(rk==3) lerr = dispTable('iir', ttl, i=cat(PACK(ki,m),PACK(kj,m)), r=cat(PACK(a(ib:ie),m)), rFmt=fm, nmax=nmax) 1070 CALL msg( lerr,'In '//TRIM(sub)//": can't display outliers table", unt)1071 IF(lerr) THEN; CALL msg("Can't display outliers table"); RETURN; END IF1079 CALL msg("can't display outliers table", sub, lerr, unt) 1080 IF(lerr) RETURN 1072 1081 END DO 1073 1082 END FUNCTION dispOutliers_1 … … 1082 1091 INTEGER, OPTIONAL, INTENT(IN) :: nmax, unit !--- Maximum number of lines to display (default: all) 1083 1092 1084 CHARACTER(LEN= 256):: mes, sub, fm='(f12.9)', prf1085 CHARACTER(LEN= 256),ALLOCATABLE :: ttl(:), vnm(:)1093 CHARACTER(LEN=maxlen) :: mes, sub, fm='(f12.9)', prf 1094 CHARACTER(LEN=maxlen), ALLOCATABLE :: ttl(:), vnm(:) 1086 1095 LOGICAL, ALLOCATABLE :: m(:) 1087 1096 INTEGER, ALLOCATABLE :: ki(:), kj(:), kl(:) … … 1096 1105 nmx = SIZE(a); IF(PRESENT(nmax)) nmx = MIN(nmx,nmax)!--- Maximum number of lines to print 1097 1106 unt = lunout; IF(PRESENT(unit)) unt = unit !--- Unit to print messages 1098 lerr = SIZE(vnm) /= nv; IF(fmsg( lerr, 'In "dispOutlayers_2": SIZE(nam) /= SIZE(a,2)' ,unt)) RETURN1099 lerr = SIZE(a,1) /= SIZE(ll); IF(fmsg( lerr,'In '//TRIM(sub)//': "ll" and "a" sizes mismatch',unt)) RETURN1100 lerr = SIZE(a,1) /= PRODUCT(n); IF(fmsg( lerr,'In '//TRIM(sub)//': profile "n" does not match "a" and "ll"',unt)) RETURN1107 lerr = SIZE(vnm) /= nv; IF(fmsg('SIZE(nam) /= SIZE(a,2)', sub, lerr, unt)) RETURN 1108 lerr = SIZE(a,1) /= SIZE(ll); IF(fmsg('"ll" and "a" sizes mismatch', sub, lerr, unt)) RETURN 1109 lerr = SIZE(a,1) /= PRODUCT(n); IF(fmsg('profile "n" does not match "a" and "ll"', sub, lerr, unt)) RETURN 1101 1110 1102 1111 SELECT CASE(rk1) !--- Indices list … … 1116 1125 IF(rk == 3) lerr = dispTable(prf, ttl, i = cat(PACK(ki,ll),PACK(kj,ll),PACK(kl,ll)), & 1117 1126 r = val, rFmt=fm, nmax=nmax) 1118 CALL msg( lerr,'In '//TRIM(sub)//": can't display outliers table", unt)1127 CALL msg("can't display outliers table", sub, lerr, unt) 1119 1128 END FUNCTION dispOutliers_2 1120 1129 !============================================================================================================================== … … 1125 1134 !============================================================================================================================== 1126 1135 LOGICAL FUNCTION reduceExpr_1(str, val) RESULT(lerr) 1127 CHARACTER(LEN=*), INTENT(IN) :: str1128 CHARACTER(LEN= 256),INTENT(OUT) :: val1129 1130 CHARACTER(LEN= 256):: v1131 CHARACTER(LEN=1024) :: s, vv1136 CHARACTER(LEN=*), INTENT(IN) :: str 1137 CHARACTER(LEN=maxlen), INTENT(OUT) :: val 1138 1139 CHARACTER(LEN=maxlen) :: v 1140 CHARACTER(LEN=1024) :: s, vv 1132 1141 CHARACTER(LEN=1024), ALLOCATABLE :: vl(:) 1133 1142 INTEGER, ALLOCATABLE :: ip(:) … … 1141 1150 ll = strCount(s,')',nn) 1142 1151 lerr = nl /= nn 1143 IF(fmsg( lerr, 'Mismatching number of opening and closing parenthesis: '//TRIM(s))) RETURN1152 IF(fmsg('Mismatching number of opening and closing parenthesis: '//TRIM(s), ll=lerr)) RETURN 1144 1153 nl = 2*nl-1 1145 1154 … … 1175 1184 !============================================================================================================================== 1176 1185 LOGICAL FUNCTION reduceExpr_basic(str, val) RESULT(lerr) 1177 CHARACTER(LEN=*), INTENT(IN) :: str1178 CHARACTER(LEN=*), INTENT(OUT) :: val1179 DOUBLE PRECISION, ALLOCATABLE :: vl(:)1180 INTEGER, ALLOCATABLE :: id(:)1181 CHARACTER(LEN= 256), ALLOCATABLE :: ky(:)1182 CHARACTER(LEN=1), ALLOCATABLE :: op(:)1186 CHARACTER(LEN=*), INTENT(IN) :: str 1187 CHARACTER(LEN=*), INTENT(OUT) :: val 1188 DOUBLE PRECISION, ALLOCATABLE :: vl(:) 1189 INTEGER, ALLOCATABLE :: id(:) 1190 CHARACTER(LEN=maxlen), ALLOCATABLE :: ky(:) 1191 CHARACTER(LEN=1), ALLOCATABLE :: op(:) 1183 1192 1184 1193 CHARACTER(LEN=1024) :: s … … 1194 1203 vl = str2dble(ky) !--- Conversion to doubles 1195 1204 lerr = ANY(vl >= HUGE(1.d0)) 1196 IF(fmsg( lerr,'Some values are non-numeric in: '//TRIM(s))) RETURN!--- Non-numerical values found1205 IF(fmsg('Some values are non-numeric in: '//TRIM(s), ll=lerr)) RETURN !--- Non-numerical values found 1197 1206 DO io = 1, SIZE(op) !--- Loop on known operators (order matters !) 1198 1207 DO i = SIZE(id), 1, -1 !--- Loop on found operators … … 1218 1227 !============================================================================================================================== 1219 1228 FUNCTION reduceExpr_m(str, val) RESULT(lerr) 1220 LOGICAL, ALLOCATABLE :: lerr(:)1221 CHARACTER(LEN=*), INTENT(IN) :: str(:)1222 CHARACTER(LEN= 256), ALLOCATABLE, INTENT(OUT) :: val(:)1229 LOGICAL, ALLOCATABLE :: lerr(:) 1230 CHARACTER(LEN=*), INTENT(IN) :: str(:) 1231 CHARACTER(LEN=maxlen), ALLOCATABLE, INTENT(OUT) :: val(:) 1223 1232 INTEGER :: i 1224 1233 ALLOCATE(lerr(SIZE(str)),val(SIZE(str))) … … 1277 1286 END FUNCTION str2dble 1278 1287 !============================================================================================================================== 1279 ELEMENTAL CHARACTER(LEN= 256) FUNCTION bool2str(b) RESULT(out)1288 ELEMENTAL CHARACTER(LEN=maxlen) FUNCTION bool2str(b) RESULT(out) 1280 1289 LOGICAL, INTENT(IN) :: b 1281 1290 WRITE(out,*)b … … 1283 1292 END FUNCTION bool2str 1284 1293 !============================================================================================================================== 1285 ELEMENTAL CHARACTER(LEN= 256) FUNCTION int2str(i, nDigits) RESULT(out)1294 ELEMENTAL CHARACTER(LEN=maxlen) FUNCTION int2str(i, nDigits) RESULT(out) 1286 1295 INTEGER, INTENT(IN) :: i 1287 1296 INTEGER, OPTIONAL, INTENT(IN) :: nDigits … … 1292 1301 END FUNCTION int2str 1293 1302 !============================================================================================================================== 1294 ELEMENTAL CHARACTER(LEN= 256) FUNCTION real2str(r,fmt) RESULT(out)1303 ELEMENTAL CHARACTER(LEN=maxlen) FUNCTION real2str(r,fmt) RESULT(out) 1295 1304 REAL, INTENT(IN) :: r 1296 1305 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: fmt … … 1300 1309 END FUNCTION real2str 1301 1310 !============================================================================================================================== 1302 ELEMENTAL CHARACTER(LEN= 256) FUNCTION dble2str(d,fmt) RESULT(out)1311 ELEMENTAL CHARACTER(LEN=maxlen) FUNCTION dble2str(d,fmt) RESULT(out) 1303 1312 DOUBLE PRECISION, INTENT(IN) :: d 1304 1313 CHARACTER(LEN=*), OPTIONAL, INTENT(IN) :: fmt … … 1367 1376 CHARACTER(LEN=*), INTENT(IN) :: message, items, reason 1368 1377 INTEGER, OPTIONAL, INTENT(IN) :: nmax 1369 CHARACTER(LEN= 256), ALLOCATABLE :: s(:)1378 CHARACTER(LEN=maxlen), ALLOCATABLE :: s(:) 1370 1379 INTEGER :: i, nmx 1371 1380 nmx = 256; IF(PRESENT(nmax)) nmx=nmax -
trac_types_mod.F90
r1 r2 1 1 MODULE trac_types_mod 2 2 3 USE strings_mod, ONLY: maxlen 4 PRIVATE 5 3 6 !=== TRACERS DESCRIPTOR DERIVED TYPE AND ASSOCIATED ROUTINES INTERFACES ======================================================= 4 PRIVATE 5 PUBLIC :: tra, iso, kys 7 PUBLIC :: trac_type, isot_type, keys_type 6 8 !------------------------------------------------------------------------------------------------------------------------------ 7 TYPE kys!=== TYPE FOR A SET OF KEYS ASSOCIATED TO AN ELEMENT8 CHARACTER(LEN= 256) :: name!--- Tracer name9 CHARACTER(LEN= 256), ALLOCATABLE :: key(:)!--- Keys string list10 CHARACTER(LEN= 256), ALLOCATABLE :: val(:)!--- Corresponding values string list11 END TYPE k ys9 TYPE :: keys_type !=== TYPE FOR A SET OF KEYS ASSOCIATED TO AN ELEMENT 10 CHARACTER(LEN=maxlen) :: name !--- Tracer name 11 CHARACTER(LEN=maxlen), ALLOCATABLE :: key(:) !--- Keys string list 12 CHARACTER(LEN=maxlen), ALLOCATABLE :: val(:) !--- Corresponding values string list 13 END TYPE keys_type 12 14 !------------------------------------------------------------------------------------------------------------------------------ 13 TYPE tra !=== TYPE FOR SINGLE TRACER 14 CHARACTER(LEN=256) :: name = '' !--- Name 15 CHARACTER(LEN=256) :: nam1 = '' !--- Generation 1 ancestor name 16 CHARACTER(LEN=256) :: prnt = '' !--- Parent name 17 CHARACTER(LEN=256) :: lnam = '' !--- Long name (with adv. scheme) 18 CHARACTER(LEN=256) :: type = 'tracer' !--- Type (so far: 'tracer'/'tag') 19 CHARACTER(LEN=256) :: phas = 'g' !--- Phase ('g'as/'l'iquid/'s'olid) 20 CHARACTER(LEN=256) :: comp !--- Coma-separated list of components (Ex: lmdz,inca) 21 INTEGER :: iadv = 10 !--- Advection scheme used 22 INTEGER :: igen = 1 !--- Generation number (>=1) 23 INTEGER :: itr = 0 !--- Index in tr_seri (0: not in physics) 24 INTEGER :: iprnt = 0 !--- Parent index 25 INTEGER, ALLOCATABLE :: idesc(:) !--- Descendants index (in growing generation order) 26 INTEGER :: ndesc = 0 !--- Number of descendants (all generations) 27 INTEGER :: nchld = 0 !--- Number of childs (first generation) 28 INTEGER :: iso_igr = 0 !--- Isotopes group index in isotopes(:) 29 INTEGER :: iso_num = 0 !--- Isotope name index in isotopes(iso_igr)%trac(:) 30 INTEGER :: iso_zon = 0 !--- Isotope zone index in isotopes(iso_igr)%zone(:) 31 INTEGER :: iso_pha = 0 !--- Isotope phase index in isotopes(iso_igr)%phas 32 TYPE(kys) :: keys !--- <key>=<val> pairs vector 33 END TYPE tra 15 TYPE :: trac_type !=== TYPE FOR A SINGLE TRACER NAMED "name" 16 CHARACTER(LEN=maxlen) :: name = '' !--- Name of the tracer 17 CHARACTER(LEN=maxlen) :: gen0Name = '' !--- First generation ancestor name 18 CHARACTER(LEN=maxlen) :: parent = '' !--- Parent name 19 CHARACTER(LEN=maxlen) :: longName = '' !--- Long name (with advection scheme suffix) 20 CHARACTER(LEN=maxlen) :: type = 'tracer' !--- Type (so far: 'tracer' / 'tag') 21 CHARACTER(LEN=maxlen) :: phase = 'g' !--- Phase ('g'as / 'l'iquid / 's'olid) 22 CHARACTER(LEN=maxlen) :: component !--- Coma-separated list of components (Ex: lmdz,inca) 23 INTEGER :: iadv = 10 !--- Advection scheme used 24 INTEGER :: iGeneration = 1 !--- Generation number (>=1) 25 LOGICAL :: isAdvected = .FALSE. !--- "true" tracers: iadv > 0 . COUNT( isAdvected) =nqtrue 26 LOGICAL :: isH2Ofamily = .FALSE. !--- H2O tracers/isotopes/tags. COUNT(.NOT.isH2Ofamily)=nqtottr 27 INTEGER :: iqParent = 0 !--- Parent index 28 INTEGER, ALLOCATABLE :: iqDescen(:) !--- Descendants index (in growing generation order) 29 INTEGER :: nqDescen = 0 !--- Number of descendants (all generations) 30 INTEGER :: nqChilds = 0 !--- Number of childs (first generation) 31 INTEGER :: iso_iGroup = 0 !--- Isotopes group index in isotopes(:) 32 INTEGER :: iso_iName = 0 !--- Isotope name index in isotopes(iso_iGroup)%trac(:) 33 INTEGER :: iso_iZone = 0 !--- Isotope zone index in isotopes(iso_iGroup)%zone(:) 34 INTEGER :: iso_iPhase = 0 !--- Isotope phase index in isotopes(iso_iGroup)%phas 35 TYPE(keys_type) :: keys !--- <key>=<val> pairs vector 36 END TYPE trac_type 34 37 !------------------------------------------------------------------------------------------------------------------------------ 35 TYPE iso !=== TYPE FOR ISOTOPES FAMILY DESCENDING ON TRACER "prnt" 36 CHARACTER(LEN=256) :: prnt !--- Isotopes family name (parent tracer name ; ex: H2O) 37 LOGICAL :: check=.FALSE. !--- Triggering of the checking routines 38 TYPE(kys), ALLOCATABLE :: keys(:) !--- Isotopes keys/values pairs list (length: niso) 39 CHARACTER(LEN=256), ALLOCATABLE :: trac(:) !--- Isotopes + tagging tracers list (length: nitr) 40 CHARACTER(LEN=256), ALLOCATABLE :: zone(:) !--- Geographic tagging zones names list 41 CHARACTER(LEN=256) :: phas = 'g' !--- Phases list: [g][l][s] 42 INTEGER :: niso=0, nzon=0, nitr=0, npha=0!--- Number of isotopes, zones, total isotopes and phases 43 INTEGER, ALLOCATABLE :: iTraPha(:,:) ! (iqiso) !--- Idx in "trac(1:niso)" = f(name(1:nitr)),phas) 44 INTEGER, ALLOCATABLE :: iZonIso(:,:) ! (index_trac) !--- Idx in "trac(1:nitr)" = f(zone, name(1:niso)) 45 END TYPE iso 38 TYPE :: isot_type !=== TYPE FOR AN ISOTOPES FAMILY DESCENDING ON TRACER "parent" 39 CHARACTER(LEN=maxlen) :: parent !--- Isotopes family name (parent tracer name ; ex: H2O) 40 LOGICAL :: check=.FALSE. !--- Triggering of the checking routines 41 TYPE(keys_type), ALLOCATABLE :: keys(:) !--- Isotopes keys/values pairs list (length: niso) 42 CHARACTER(LEN=maxlen), ALLOCATABLE :: trac(:) !--- Isotopes + tagging tracers list (length: nitr) 43 CHARACTER(LEN=maxlen), ALLOCATABLE :: zone(:) !--- Geographic tagging zones names list (length: nzon) 44 CHARACTER(LEN=maxlen) :: phase = 'g' !--- Phases list: [g][l][s] (length: npha) 45 INTEGER :: niso = 0 !--- Number of isotopes, excluding tagging tracers 46 INTEGER :: nzon = 0 !--- Number of geographic tagging zones 47 INTEGER :: nitr = 0 !--- Number of isotopes, including tagging tracers 48 INTEGER :: npha = 0 !--- Number phases 49 INTEGER, ALLOCATABLE :: iTraPha(:,:) !--- Idx in "trac(1:niso)" = f(name(1:nitr)),phas) 50 !--- "iTraPha" former name: "iqiso" 51 INTEGER, ALLOCATABLE :: iZonIso(:,:) !--- Idx in "trac(1:nitr)" = f(zone, name(1:niso)) 52 !--- "iZonIso" former name: "index_trac" 53 END TYPE isot_type 46 54 47 55 END MODULE trac_types_mod
Note: See TracChangeset
for help on using the changeset viewer.