Changeset 1795 for trunk/LMDZ.TITAN/libf
- Timestamp:
- Oct 12, 2017, 12:26:18 PM (7 years ago)
- Location:
- trunk/LMDZ.TITAN/libf/phytitan
- Files:
-
- 2 added
- 1 deleted
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LMDZ.TITAN/libf/phytitan/calchim.F90
r1787 r1795 164 164 enddo 165 165 rmil(NLEV) = rinter(NLEV)+(rinter(NLEV)-rinter(NLEV-1))/2. 166 ! rmil et rinter ne servent que pour la diffusion (> plafond-100km) donc ok en moyenne planetaire 166 167 167 168 ! lecture de tcp.ver, une seule fois -
trunk/LMDZ.TITAN/libf/phytitan/callkeys_mod.F90
r1788 r1795 4 4 logical,save :: callrad,corrk,calldifv,UseTurbDiff 5 5 !$OMP THREADPRIVATE(callrad,corrk,calldifv,UseTurbDiff) 6 logical,save :: calladj,callsoil ,callchim7 !$OMP THREADPRIVATE(calladj,callsoil ,callchim)6 logical,save :: calladj,callsoil 7 !$OMP THREADPRIVATE(calladj,callsoil) 8 8 logical,save :: season,diurnal,tlocked,rings_shadow,lwrite 9 9 !$OMP THREADPRIVATE(season,diurnal,tlocked,rings_shadow,lwrite) … … 14 14 logical,save :: strictboundcorrk 15 15 !$OMP THREADPRIVATE(strictboundcorrk) 16 17 logical,save :: callchim, callmufi, callclouds 18 !$OMP THREADPRIVATE(callchim,callmufi,callclouds) 16 19 17 20 logical,save :: enertest … … 36 39 37 40 integer,save :: ichim 41 !$OMP THREADPRIVATE(ichim) 42 38 43 integer,save :: iddist 39 44 integer,save :: iradia 40 45 integer,save :: startype 41 !$OMP THREADPRIVATE(ichim,iddist,iradia,startype) 46 !$OMP THREADPRIVATE(iddist,iradia,startype) 47 48 real,save :: df_mufi, rm_mufi, rho_aer_mufi 49 real,save :: p_prod, tx_prod, rc_prod 50 real,save :: air_rad 51 !$OMP THREADPRIVATE(df_mufi, rm_mufi, rho_aer_mufi,p_prod,tx_prod,rc_prod,air_rad) 42 52 43 53 real,save :: Fat1AU -
trunk/LMDZ.TITAN/libf/phytitan/datafile_mod.F90
r1788 r1795 5 5 6 6 ! Main directory: 'datadir': 7 ! Default for Berserker @ UChicago:8 ! character(len=300) :: datadir='/home/rwordsworth/datagcm'9 ! Default for Gnome Idataplex:10 ! character(len=300) :: datadir='/san/home/rdword/gcm/datagcm'11 7 ! Default for LMD machines: 12 character(len=300),save :: datadir=' /u/lmdz/WWW/planets/LMDZ.GENERIC/datagcm'8 character(len=300),save :: datadir='datagcm' 13 9 !$OMP THREADPRIVATE(datadir) 14 10 … … 18 14 character(len=12),parameter :: surfdir="surface_data" 19 15 16 ! Default directory for microphysics 17 character(LEN=300),save :: config_mufi ='datagcm/microphysics/config.cfg' 18 20 19 end module datafile_mod 21 20 !----------------------------------------------------------------------- -
trunk/LMDZ.TITAN/libf/phytitan/inifis_mod.F90
r1788 r1795 10 10 11 11 use radinc_h, only: ini_radinc_h 12 use datafile_mod, only: datadir 12 use datafile_mod, only: datadir,config_mufi 13 13 use comdiurn_h, only: sinlat, coslat, sinlon, coslon 14 14 use comgeomfi_h, only: totarea, totarea_planet … … 319 319 call getin_p("ichim",ichim) 320 320 write(*,*)" ichim = ",ichim 321 322 ! Microphysics 323 324 write(*,*) "Run with or without microphysics?" 325 callmufi=.false. ! default value 326 call getin_p("callmufi",callmufi) 327 write(*,*)" callmufi = ",callmufi 328 329 ! sanity check 330 if (callmufi.and.(.not.tracer)) then 331 print*,"You are running microphysics without tracer" 332 print*,"Please start again with tracer =.true." 333 stop 334 endif 335 336 write(*,*) "Compute clouds?" 337 callclouds=.false. ! default value 338 call getin_p("callclouds",callclouds) 339 write(*,*)" callclouds = ",callclouds 340 341 ! sanity check 342 if (callclouds.and.(.not.callmufi)) then 343 print*,"You are trying to make clouds without microphysics !" 344 print*,"Please start again with callmufi =.true." 345 stop 346 endif 347 348 write(*,*) "Fractal dimension ?" 349 df_mufi=2.0 ! default value 350 call getin_p("df_mufi",df_mufi) 351 352 write(*,*) "Monomer radius (m) ?" 353 rm_mufi=6.66e-08 ! default value 354 call getin_p("rm_mufi",rm_mufi) 355 356 write(*,*) "Aerosol density (kg.m-3)?" 357 rho_aer_mufi=1.e3 ! default value 358 call getin_p("rho_aer_mufi",rho_aer_mufi) 359 360 write(*,*) "Pressure level of aer. production (Pa) ?" 361 p_prod=1.0 ! default value 362 call getin_p("p_prod",p_prod) 363 364 write(*,*) "Aerosol production rate (kg.m-2.s-1) ?" 365 tx_prod=3.5e-13 ! default value 366 call getin_p("tx_prod",tx_prod) 367 368 write(*,*) "Equivalent radius production (m) ?" 369 rc_prod=2.0e-8 ! default value 370 call getin_p("rc_prod",rc_prod) 371 372 write(*,*) "Radius of air (nitrogen) molecule (m) ?" 373 air_rad=1.75e-10 ! default value 374 call getin_p("air_rad",air_rad) 375 376 write(*,*) "Path to microphys. config file ?" 377 config_mufi='datagcm/microphysics/config.cfg' ! default value 378 call getin_p("config_mufi",config_mufi) 321 379 322 380 ! Soil model -
trunk/LMDZ.TITAN/libf/phytitan/physiq_mod.F90
r1789 r1795 22 22 use geometry_mod, only: latitude, longitude, cell_area 23 23 USE comgeomfi_h, only: totarea, totarea_planet 24 USE tracer_h , only: noms, mmol24 USE tracer_h 25 25 use time_phylmdz_mod, only: ecritphy, iphysiq, nday 26 26 use phyetat0_mod, only: phyetat0 … … 32 32 use comcstfi_mod, only: pi, g, rcp, r, rad, mugaz, cpp 33 33 use time_phylmdz_mod, only: daysec 34 use logic_mod, only: moyzon_ch 34 use logic_mod, only: moyzon_ch, moyzon_mu 35 35 use moyzon_mod, only: tmoy, playmoy, zphibar, zphisbar, zplevbar, & 36 36 zplaybar, zzlevbar, zzlaybar, ztfibar … … 73 73 ! V. Tracers 74 74 ! V.1. Chemistry 75 ! V.2. Microphysics 75 76 ! V.3. Updates (pressure variations, surface budget). 76 77 ! V.4. Surface Tracer Update. … … 159 160 ! ------- 160 161 162 161 163 integer,intent(in) :: ngrid ! Number of atmospheric columns. 162 164 integer,intent(in) :: nlayer ! Number of atmospheric layers. … … 277 279 278 280 real zdqchi(ngrid,nlayer,nq) ! Chemical tendency ( chemistry routine ). 279 real zdqmph(ngrid,nlayer,nq) ! Microphysical tendency ( condensation routine only for now, no microphysical routines ). 281 real zdqcond(ngrid,nlayer,nq) ! Condensation tendency ( chemistry routine ). 282 283 real zdqmufi(ngrid,nlayer,nq) ! Microphysical tendency. 280 284 281 285 ! For Winds : (m/s/s) … … 349 353 ! ---------------------------------------------------------------------------- 350 354 351 integer,parameter :: nmicro=0 ! Temporary ! To be put in start/def 355 character*10,dimension(:),allocatable,save :: nomqy 356 357 !$OMP THREADPRIVATE(nomqy) 352 358 353 359 real ctimestep ! Chemistry timestep (s) … … 356 362 real temp_eq(nlayer), press_eq(nlayer) 357 363 real zplev(ngrid,nlayer+1),zplay(ngrid,nlayer) 358 ! real zzlev(ngrid,nlayer+1),zzlay(ngrid,nlayer)359 364 real ztemp(ngrid,nlayer) 360 365 361 real ychim(ngrid,nlayer,nq-nmicro) 362 363 real rat_mmol(nq) ! Molar fraction ratio 364 365 ! 2D vmr tendencies ( chemistry and condensation ) 366 real,dimension(:,:,:),allocatable,save :: dycchi 367 ! Must be saved since chemistry is not called every step 368 369 real dycmph(ngrid,nlayer,nq-nmicro) 370 ! ---------------------------------------------------------- 371 372 real,dimension(:,:),allocatable,save :: qysat 373 374 character*10,dimension(:),allocatable,save :: nomqy 375 !$OMP THREADPRIVATE(dycchi,qysat,nomqy) 366 real , allocatable, dimension(:,:,:),save :: ychim 367 368 ! 2D vmr tendencies ( chemistry and condensation ) for chem. tracers 369 real,dimension(:,:,:),allocatable,save :: dycchi ! Saved since chemistry is not called every step 370 real dyccond(ngrid,nlayer,nq) 371 372 real,dimension(:,:),allocatable,save :: qysat 373 374 !$OMP THREADPRIVATE(ychim,dycchi,qysat) 376 375 377 376 real,dimension(:),allocatable,save :: tankCH4 ! Depth of surface methane tank … … 379 378 380 379 !----------------------------------------------------------------------------- 380 ! Interface to calmufi 381 ! --> needed in order to pass assumed-shape arrays. Otherwise we must put calmufi in a module 382 ! (to have an explicit generated by the compiler). 383 ! Or one can put calmufi in MMP_GCM module (in muphytitan). 384 INTERFACE 385 SUBROUTINE calmufi(plev, zlev, play, zlay, temp, pq, zdq) 386 REAL(kind=8), DIMENSION(:,:), INTENT(IN) :: plev !! Pressure levels (Pa). 387 REAL(kind=8), DIMENSION(:,:), INTENT(IN) :: zlev !! Altitude levels (m). 388 REAL(kind=8), DIMENSION(:,:), INTENT(IN) :: play !! Pressure layers (Pa). 389 REAL(kind=8), DIMENSION(:,:), INTENT(IN) :: zlay !! Altitude at the center of each layer (m). 390 REAL(kind=8), DIMENSION(:,:), INTENT(IN) :: temp !! Temperature at the center of each layer (K). 391 REAL(kind=8), DIMENSION(:,:,:), INTENT(IN) :: pq !! Tracers (\(kg.kg^{-1}}\)). 392 REAL(kind=8), DIMENSION(:,:,:), INTENT(OUT) :: zdq !! Tendency for tracers (\(kg.kg^{-1}}\)). 393 END SUBROUTINE calmufi 394 END INTERFACE 381 395 382 396 !================================================================================================== … … 390 404 ! -------------------------------- 391 405 if (firstcall) then 406 ! initracer: 407 ! initialize nmicro, 408 call initracer2(nq,nametrac) 409 410 ! ---------------------------------------------------------------------------- 392 411 393 412 ! Allocate saved arrays. … … 423 442 ALLOCATE(dycchi(ngrid,nlayer,nq-nmicro)) 424 443 ALLOCATE(qysat(nlayer,nq-nmicro)) 425 ALLOCATE(nomqy(nq-nmicro+1)) 444 ALLOCATE(nomqy(nq-nmicro+1)) ! +1 because of hv 426 445 427 446 ! This is defined in comsaison_h … … 439 458 zdtlw(:,:) = 0.0 440 459 441 442 ! Initialize tracer names, indexes and properties. 443 ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 444 IF (.NOT.ALLOCATED(noms)) ALLOCATE(noms(nq)) ! (because noms is an argument of physdem1 whether or not tracer is on) 445 if (tracer) then 446 call initracer(ngrid,nq,nametrac) 447 endif 448 449 rat_mmol(:) = mmol(:) / mugaz 460 ! Initialize names, timestep and saturation profiles for chemistry 461 ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 462 463 if ( callchim .and. (nq.gt.nmicro) ) then 464 465 ctimestep = ptimestep*REAL(ichim) 466 467 do iq=nmicro+1,nq 468 nomqy(iq-nmicro) = nametrac(iq) 469 enddo 470 471 nomqy(nq-nmicro+1) = "HV" 472 473 ! qysat is taken at the equator ( small variations of t,p) 474 temp_eq(:) = tmoy(:) 475 press_eq(:) = playmoy(:)/100. ! en mbar 476 477 call inicondens(nq-nmicro,press_eq,temp_eq,nomqy,qysat) 478 479 zdqchi(:,:,:) = 0.0 480 zdqcond(:,:,:) = 0.0 481 482 endif 483 484 ! Initialize microphysics. 485 ! ~~~~~~~~~~~~~~~~~~~~~~~~ 486 487 IF ( callmufi ) THEN 488 489 call inimufi(nq,ptimestep) 490 491 ENDIF 492 450 493 451 494 ! Read 'startfi.nc' file. … … 485 528 call iniorbit(apoastr,periastr,year_day,peri_day,obliquit) 486 529 487 488 530 if(tlocked)then 489 531 print*,'Planet is tidally locked at resonance n=',nres … … 533 575 endif 534 576 577 ! Sanity check for microphysics 578 if ( ((.not.moyzon_mu).and.(callmufi)) ) then 579 print *, "moyzon_mu=",moyzon_mu," and callmufi=",callmufi 580 print *, "Please activate zonal mean to run microphysics (for now) !" 581 stop 582 endif 583 535 584 ! Sanity check for chemistry 536 if ( ( (moyzon_ch).and.(.not.callchim)) .or. ((.not.moyzon_ch).and.(callchim)) ) then585 if ( (.not.moyzon_ch) .and. (callchim) ) then 537 586 print *, "moyzon_ch=",moyzon_ch," and callchim=",callchim 538 print *, " This is not compatible..."587 print *, "Please activate zonal mean to run chemistry !" 539 588 stop 540 589 endif 541 590 542 ! Initialize names, timestep and saturation profiles for chemistry543 544 if ( callchim .and. (nq.gt.nmicro) ) then545 546 ctimestep = ptimestep*REAL(ichim)547 548 do iq=nmicro+1,nq549 nomqy(iq-nmicro) = nametrac(iq)550 enddo551 552 nomqy(nq-nmicro+1) = "HV"553 554 ! qysat is taken at the equator ( small variations of t,p)555 temp_eq(:) = tmoy(:)556 press_eq(:) = playmoy(:)/100. ! en mbar557 558 call inicondens(nq-nmicro,press_eq,temp_eq,nomqy,qysat)559 560 endif561 591 562 592 ! XIOS outputs … … 647 677 ! -------------------------------Taken from old Titan -------------------------- 648 678 ! zonal averages needed 649 if (moyzon_ch ) then679 if (moyzon_ch .or. moyzon_mu) then 650 680 651 681 zzlaybar(1,:)=(zphibar(1,:)+zphisbar(1))/g … … 681 711 682 712 endif ! moyzon 713 683 714 ! ------------------------------------------------------------------------------------- 684 685 715 ! Compute potential temperature 686 716 ! Note : Potential temperature calculation may not be the same in physiq and dynamic... … … 981 1011 ! V.1. Chemistry 982 1012 ! ------------------------- 1013 983 1014 if (callchim) then 984 1015 985 ! U tilisation de la moyenne zonale danscalchim1016 ! Using zonal mean for calchim 986 1017 zplev(:,:) = zplevbar(:,:) 987 1018 zplay(:,:) = zplaybar(:,:) … … 990 1021 ztemp(:,:) = ztfibar(:,:) 991 1022 1023 allocate(ychim(ngrid,nlayer,nq-nmicro)) 1024 992 1025 if (nq.gt.nmicro) then 993 1026 do iq = nmicro+1,nq … … 997 1030 998 1031 ! Condensation tendency after the transport 999 do iq= 1,nq-nmicro1032 do iq=nmicro+1,nq 1000 1033 do l=1,nlayer 1001 1034 do ig=1,ngrid 1002 if ( ychim(ig,l,iq ).gt.qysat(l,iq) ) then1003 dyc mph(ig,l,nmicro+iq)= ( -ychim(ig,l,iq)+qysat(l,iq) ) / ptimestep1035 if ( ychim(ig,l,iq-nmicro).gt.qysat(l,iq-nmicro) ) then 1036 dyccond(ig,l,iq)= ( -ychim(ig,l,iq-nmicro)+qysat(l,iq-nmicro) ) / ptimestep 1004 1037 endif 1005 1038 enddo … … 1007 1040 enddo 1008 1041 1009 if( mod(icount-1,ichim).eq.0.) then 1042 if ( callclouds ) dyccond(:,:,ices_indx) = 0.0 ! Condensation will be calculated in the cloud microphysics 1043 1044 if( mod(icount-1,ichim).eq.0. ) then 1010 1045 1011 print *, "On passe dans la chimie..." 1012 1046 print *, "We enter in the chemistry ..." 1013 1047 call calchim(ngrid,nq-nmicro,ychim,nomqy,declin,zls,ctimestep, & 1014 1048 ztemp,zplay,zplev,zzlay,zzlev,dycchi,nlayer+70) … … 1018 1052 endif 1019 1053 1054 ! TEMPORARY COMMENT 1055 ! These conversions as well as 2D/1D should be put in phytrac 1056 ! ( GCM-friendly tracers and tendencies -> format for photochem and microphys ) 1057 1020 1058 if (nq.gt.nmicro) then 1021 ! We convert tendencies backto mass mixing ratio1059 ! We convert tendencies to mass mixing ratio 1022 1060 do iq=nmicro+1,nq 1023 zdqchi(:,:,iq) = dycchi(:,:,iq-nmicro)/ rat_mmol(iq)1024 zdq mph(:,:,iq) = dycmph(:,:,iq-nmicro) / rat_mmol(iq)1061 zdqchi(:,:,iq) = dycchi(:,:,iq-nmicro) / rat_mmol(iq) 1062 zdqcond(:,:,iq) = dyccond(:,:,iq) / rat_mmol(iq) 1025 1063 enddo 1026 1064 1027 1065 pdq(1:ngrid,1:nlayer,1:nq) = pdq(1:ngrid,1:nlayer,1:nq) + & 1028 zdqchi(1:ngrid,1:nlayer,1:nq) + zdq mph(1:ngrid,1:nlayer,1:nq)1066 zdqchi(1:ngrid,1:nlayer,1:nq) + zdqcond(1:ngrid,1:nlayer,1:nq) 1029 1067 1030 1068 endif 1031 1069 1032 endif 1070 endif ! end of 'callchim' 1071 1072 ! ------------------- 1073 ! V.2 Microphysics 1074 ! ------------------- 1075 1076 if (callmufi) then 1077 1078 ! Using zonal mean for microphysics 1079 zplev(:,:) = zplevbar(:,:) 1080 zplay(:,:) = zplaybar(:,:) 1081 zzlev(:,:) = zzlevbar(:,:) 1082 zzlay(:,:) = zzlaybar(:,:) 1083 ztemp(:,:) = ztfibar(:,:) 1084 1085 ! Inside this routine we will split 2D->1D, intensive->extensive and separate different types of tracers 1086 ! Should be put in phytrac 1087 1088 call calmufi(zplev,zzlev,zplay,zzlay,ztemp,pq,zdqmufi) 1089 1090 pdq(1:ngrid,1:nlayer,1:nq) = pdq(1:ngrid,1:nlayer,1:nq) + zdqmufi(1:ngrid,1:nlayer,1:nq) 1091 1092 endif ! end of 'callmufi' 1033 1093 1034 1094 ! --------------- … … 1346 1406 1347 1407 !call writediagfi(ngrid,"ALB","Surface albedo"," ",2,albedo_equivalent) 1348 !call writediagfi(ngrid,"ALB_1st","First Band Surface albedo"," ",2,albedo(:,1))1349 1408 call writediagfi(ngrid,"ISR","incoming stellar rad.","W m-2",2,fluxtop_dn) 1350 1409 call writediagfi(ngrid,"ASR","absorbed stellar rad.","W m-2",2,fluxabs_sw) 1351 1410 call writediagfi(ngrid,"OLR","outgoing longwave rad.","W m-2",2,fluxtop_lw) 1352 call writediagfi(ngrid,"shad","rings"," ", 2, fract)1353 1411 1354 1412 ! call writediagfi(ngrid,"ASRcs","absorbed stellar rad (cs).","W m-2",2,fluxabs_sw1) … … 1403 1461 if (tracer) then 1404 1462 1405 do iq=1,nq 1406 call writediagfi(ngrid,noms(iq),noms(iq),'kg/kg',3,zq(1,1,iq)) 1407 call writediagfi(ngrid,trim(noms(iq))//'_surf',trim(noms(iq))//'_surf', & 1408 'kg m^-2',2,qsurf_hist(1,iq) ) 1409 1410 ! call writediagfi(ngrid,trim(noms(iq))//'_surf',trim(noms(iq))//'_surf', & 1411 ! 'kg m^-2',2,qsurf(1,iq) ) 1412 1413 enddo ! end of 'nq' loop 1414 1463 if (callmufi) then ! For now we assume an given order for tracers ! 1464 call writediagfi(ngrid,"mu_m0as","Spherical mode 0th order moment",'kg/kg',3,zq(:,:,1)) 1465 call writediagfi(ngrid,"mu_m3as","Spherical mode 3rd order moment",'kg/kg',3,zq(:,:,2)) 1466 call writediagfi(ngrid,"mu_m0af","Fractal mode 0th order moment",'kg/kg',3,zq(:,:,3)) 1467 call writediagfi(ngrid,"mu_m3af","Fractal mode 3rd order moment",'kg/kg',3,zq(:,:,4)) 1468 endif ! end of 'callmufi' 1469 1415 1470 endif ! end of 'tracer' 1416 1417 1418 ! Output spectrum.1419 if(specOLR.and.corrk)then1420 call writediagspecIR(ngrid,"OLR3D","OLR(lon,lat,band)","W/m^2/cm^-1",3,OLR_nu)1421 call writediagspecVI(ngrid,"OSR3D","OSR(lon,lat,band)","W/m^2/cm^-1",3,OSR_nu)1422 endif1423 1471 1424 1472 ! XIOS outputs -
trunk/LMDZ.TITAN/libf/phytitan/tracer_h.F90
r1788 r1795 1 1 2 module tracer_h 3 4 implicit none 5 6 ! nqtot : total number of tracers 7 INTEGER, SAVE :: nqtot 8 !$OMP THREADPRIVATE(nqtot) 9 10 character*20, DIMENSION(:), ALLOCATABLE :: noms ! name of the tracer 11 real, DIMENSION(:), ALLOCATABLE :: mmol ! mole mass of tracer (g/mol-1) 12 real, DIMENSION(:), ALLOCATABLE :: rho_q ! tracer densities (kg.m-3) 13 14 !$OMP THREADPRIVATE(noms,mmol,rho_q) 15 16 ! tracer indexes: these are initialized in initracer and should be 0 if the 17 ! corresponding tracer does not exist 18 19 ! chemistry: 20 21 integer :: igcm_h 22 integer :: igcm_h2 23 integer :: igcm_ch 24 integer :: igcm_ch2s 25 integer :: igcm_ch2 26 integer :: igcm_ch3 27 integer :: igcm_ch4 28 integer :: igcm_c2 29 integer :: igcm_c2h 30 integer :: igcm_c2h2 31 integer :: igcm_c2h3 32 integer :: igcm_c2h4 33 integer :: igcm_c2h5 34 integer :: igcm_c2h6 35 integer :: igcm_c3h3 36 integer :: igcm_c3h5 37 integer :: igcm_c3h6 38 integer :: igcm_c3h7 39 integer :: igcm_c4h 40 integer :: igcm_c4h3 41 integer :: igcm_c4h4 42 integer :: igcm_c4h2s 43 integer :: igcm_ch2cch2 44 integer :: igcm_ch3cch 45 integer :: igcm_c3h8 46 integer :: igcm_c4h2 47 integer :: igcm_c4h6 48 integer :: igcm_c4h10 49 integer :: igcm_ac6h6 50 integer :: igcm_c3h2 51 integer :: igcm_c4h5 52 integer :: igcm_ac6h5 53 integer :: igcm_n2 54 integer :: igcm_n4s 55 integer :: igcm_cn 56 integer :: igcm_hcn 57 integer :: igcm_h2cn 58 integer :: igcm_chcn 59 integer :: igcm_ch2cn 60 integer :: igcm_ch3cn 61 integer :: igcm_c3n 62 integer :: igcm_hc3n 63 integer :: igcm_nccn 64 integer :: igcm_c4n2 65 66 67 !$OMP THREADPRIVATE(igcm_h,igcm_h2,igcm_ch,igcm_ch2s,igcm_ch2,igcm_ch3,igcm_ch4, & 68 !$OMP igcm_c2,igcm_c2h,igcm_c2h2,igcm_c2h3,igcm_c2h4,igcm_c2h5,igcm_c2h6, & 69 !$OMP igcm_c3h3,igcm_c3h5,igcm_c3h6,igcm_c3h7,igcm_c4h,igcm_c4h3,igcm_c4h4, & 70 !$OMP igcm_c4h2s,igcm_ch2cch2,igcm_ch3cch,igcm_c3h8,igcm_c4h2,igcm_c4h6, & 71 !$OMP igcm_c4h10,igcm_ac6h6,igcm_c3h2,igcm_c4h5,igcm_ac6h5,igcm_n2,igcm_n4s, & 72 !$OMP igcm_cn,igcm_hcn,igcm_h2cn,igcm_chcn,igcm_ch2cn,igcm_ch3cn,igcm_c3n, & 73 !$OMP igcm_hc3n,igcm_nccn,igcm_c4n2) 74 75 end module tracer_h 76 2 MODULE tracer_h 3 !! Stores data related to physics tracers. 4 !! 5 !! The module stores public global variables related to the number of tracers 6 !! available in the physics and their kind: 7 !! 8 !! Currently, tracers can be used either for chemistry process (nchimi) or 9 !! microphysics (nmicro). 10 !! 11 !! The subroutine "initracer2" initializes and performs sanity check of 12 !! the tracer definitions given in traceur.def and the required tracers in physics 13 !! (based on the run parameters). 14 !! 15 !! The module provides additional methods: 16 !! 17 !! - indexOfTracer : search for the index of a tracer in the global table (tracers_h:noms) by name. 18 !! - nameOfTracer : get the name of tracer from a given index (of the global table). 19 !! - dumpTracers : print the names of all tracers indexes given in argument. 20 !! 21 IMPLICIT NONE 22 23 INTEGER, SAVE :: nqtot = 0 !! Total number of tracers 24 INTEGER, SAVE :: nmicro = 0 !! Number of microphysics tracers. 25 INTEGER, SAVE :: nice = 0 !! Number of microphysics ice tracers (subset of nmicro). 26 INTEGER, SAVE :: nchimi = 0 !! Number of chemical (gaz species) tracers. 27 !$OMP THREADPRIVATE(nqtot,nmicro,nice,nchimi) 28 29 INTEGER, DIMENSION(:), ALLOCATABLE, SAVE :: chimi_indx !! Indexes of all chemical species tracers 30 INTEGER, DIMENSION(:), ALLOCATABLE, SAVE :: micro_indx !! Indexes of all microphysical tracers 31 INTEGER, DIMENSION(:), ALLOCATABLE, SAVE :: ices_indx !! Indexes of all ice microphysical tracers 32 33 CHARACTER(len=20), DIMENSION(:), ALLOCATABLE, SAVE :: noms !! name of the tracer 34 REAL, DIMENSION(:), ALLOCATABLE, SAVE :: mmol !! mole mass of tracer(g/mol-1) 35 REAL, DIMENSION(:), ALLOCATABLE, SAVE :: rat_mmol !! molar mass ratio 36 REAL, DIMENSION(:), ALLOCATABLE, SAVE :: rho_q !! tracer densities (kg.m-3) 37 !$OMP THREADPRIVATE(noms,mmol,rat_mmol,rho_q) 38 39 40 41 ! tracer indexes: these are initialized in initracer and should be 0 if the 42 ! corresponding tracer does not exist 43 44 45 CONTAINS 46 47 SUBROUTINE initracer2(nq,nametrac,talk_to_me) 48 !! Initialize tracer names and attributes. 49 !! 50 !! The method initializes the list of tracer names used in the physics from their 51 !! dynamics counterpart. 52 !! 53 !! In addition, it initializes arrays of indexes for the different sub-processs of the physics: 54 !! 55 !! - tracers_h:micro_indxs, the array of tracers indexes used for the microphysics. 56 !! - tracers_h:chimi_indxs, the array of tracers indexes used for the chemistry. 57 !! 58 !! The method also initializes the molar mass array (tracers_h:mmol) for the chemistry and the 59 !! molar mass ratio (tracers_h:rat_mmol). 60 !! 61 !! @note 62 !! Strict checking of chemical species name is performed here if the chemistry is activated 63 !! (see callchim variable). All the values of 'cnames' must be found in the tracers names 64 !! related to chemistry. 65 !! @note 66 !! Tests are more permissive for the microphysics and is only based on the mimimum number of 67 !! tracers expected. Strict name checking is performed in inimufi. 68 USE callkeys_mod 69 USE comcstfi_mod, only: mugaz 70 IMPLICIT NONE 71 72 INTEGER, INTENT(in) :: nq !! Total number of tracers (fixed at compile time) 73 character(len=20), DIMENSION(nq), INTENT(in) :: nametrac !! name of the tracer from dynamics (from 'traceurs.def') 74 LOGICAL, INTENT(in), OPTIONAL :: talk_to_me !! Enable verbose mode. 75 76 LOGICAL :: verb,found 77 CHARACTER(len=20) :: str 78 !! Hard-coded chemical species for Titan chemistry 79 CHARACTER(len=10), DIMENSION(44), PARAMETER :: cnames = & 80 (/"H ", "H2 ", "CH ", "CH2s ", "CH2 ", "CH3 ", & 81 "CH4 ", "C2 ", "C2H ", "C2H2 ", "C2H3 ", "C2H4 ", & 82 "C2H5 ", "C2H6 ", "C3H3 ", "C3H5 ", "C3H6 ", "C3H7 ", & 83 "C4H ", "C4H3 ", "C4H4 ", "C4H2s ", "CH2CCH2 ", "CH3CCH ", & 84 "C3H8 ", "C4H2 ", "C4H6 ", "C4H10 ", "AC6H6 ", "C3H2 ", & 85 "C4H5 ", "AC6H5 ", "N2 ", "N4S ", "CN ", "HCN ", & 86 "H2CN ", "CHCN ", "CH2CN ", "CH3CN ", "C3N ", "HC3N ", & 87 "NCCN ", "C4N2 "/) 88 !! Hard-coded chemical species molar mass (g.mol-1), shares the same indexing than cnames. 89 REAL, DIMENSION(44), PARAMETER :: cmmol = (/ & 90 1.01 , 2.0158, 13.02, 14.03, 14.03, 15.03, 16.04 , 24.02, 25.03, 26.04 , 27.05 , & 91 28.05 , 29.06 , 30.07, 39.06, 41.07, 42.08, 43.09 , 49.05, 51.07, 52.08 , 50.06 , & 92 40.07 , 40.07 , 44.11, 50.06, 54.09, 58.13, 78.1136, 38.05, 53.07, 77.1136, 28.0134, & 93 14.01 , 26.02 , 27.04, 28.05, 39.05, 40.04, 41.05 , 50.04, 51.05, 52.04 , 76.1 /) 94 95 INTEGER :: i,j,n 96 97 verb = .true. ; IF (PRESENT(talk_to_me)) verb = talk_to_me 98 99 ! nqtot could be used everywhere in the physic :) 100 nqtot=nq 101 102 IF (.NOT.ALLOCATED(noms)) ALLOCATE(noms(nq)) 103 noms(:)=nametrac(:) 104 105 ALLOCATE(rho_q(nq)) ! Defined for all tracers, currently initialized to 0.0 106 rho_q(:) = 0.0 107 108 ALLOCATE(mmol(nq),rat_mmol(nq)) ! Defined for all tracers, (actually) initialized only for chemical tracers 109 mmol(:) = 0.0 110 rat_mmol(:) = 1.0 111 112 ! Compute number of microphysics tracers: 113 ! By convention they all have the prefix "mu_" (case sensitive !) 114 nmicro = 0 115 IF (callmufi) THEN 116 DO i=1,nq 117 str = noms(i) 118 IF (str(1:3) == "mu_") nmicro = nmicro+1 119 ENDDO 120 ! Checking the expected number of tracers: 121 ! no cloud: 4 ; w cloud : 4 + 2 + (1+) 122 ! Note that we do not make assumptions on the number of chemical species for clouds, this 123 ! will be checked in inimufi. 124 IF (callclouds) THEN 125 IF (nmicro < 7) THEN 126 WRITE(*,'((a),I3,(a))') "initracer2:error: Inconsistent number of microphysical tracers & 127 &(expected at least 7 tracers,",nmicro," given)" 128 CALL abort_gcm("initracer2", "inconsistent number of tracers", 42) 129 STOP 130 ENDIF 131 ELSE IF (nmicro < 4) THEN 132 WRITE(*,'((a),I3,(a))') "initracer2:error: Inconsistent number of microphysical tracers & 133 &(expected at least 4 tracers,",nmicro," given)" 134 CALL abort_gcm("initracer2", "inconsistent number of tracers", 42) 135 ELSE IF (nmicro > 4) THEN 136 WRITE(*,'(a)') "initracer2:info: I was expecting only four tracers, you gave me & 137 &more. I'll just pretend nothing happen !" 138 ENDIF 139 ! microphysics indexes share the same values than original tracname. 140 ALLOCATE(micro_indx(nmicro)) 141 j = 1 142 DO i=1,nq 143 str = noms(i) 144 IF (str(1:3) == "mu_") THEN 145 micro_indx(j) = i 146 j=j+1 147 ENDIF 148 ENDDO 149 ELSE 150 ALLOCATE(micro_indx(nmicro)) 151 ENDIF 152 153 ! Compute number of chemical species: 154 ! simply assume that all other tracers ARE chemical species 155 nchimi = nqtot - nmicro 156 157 ! Titan chemistry requires exactly 44 tracers: 158 ! Test should be in callchim condition 159 160 IF (callchim) THEN 161 IF (nchimi < SIZE(cnames)) THEN 162 WRITE(*,*) "initracer2:error: Inconsistent number of chemical species given (",SIZE(cnames)," expected)" 163 CALL abort_gcm("initracer2", "inconsistent number of tracers", 42) 164 ENDIF 165 ALLOCATE(chimi_indx(nchimi)) 166 n = 0 ! counter on chimi_indx 167 DO j=1,SIZE(cnames) 168 found = .false. 169 DO i=1,nq 170 IF (TRIM(cnames(j)) == TRIM(noms(i))) THEN 171 n = n + 1 172 chimi_indx(n) = i 173 mmol(i) = cmmol(j) 174 rat_mmol(i) = cmmol(j)/mugaz 175 found = .true. 176 EXIT 177 ENDIF 178 ENDDO 179 IF (.NOT.found) THEN 180 WRITE(*,*) "initracer2:error: "//TRIM(cnames(j))//" is missing from tracers definition file." 181 ENDIF 182 ENDDO 183 IF (n < SIZE(cnames)) THEN 184 WRITE(*,*) "initracer2:error: Inconsistent number of chemical species given (",SIZE(cnames)," expected)" 185 CALL abort_gcm("initracer2", "inconsistent number of tracers", 42) 186 ENDIF 187 ELSE 188 ALLOCATE(chimi_indx(0)) 189 ENDIF 190 IF (verb) THEN 191 IF (callmufi.OR.callchim) WRITE(*,*) "===== INITRACER2 SPEAKING =====" 192 IF (callmufi) THEN 193 WRITE(*,*) "Found ",nmicro, "microphysical tracers" 194 call dumpTracers(micro_indx) 195 WRITE(*,*) "-------------------------------" 196 ENDIF 197 IF (callchim) THEN 198 WRITE(*,*) "Found ",nchimi, "chemical tracers" 199 call dumpTracers(chimi_indx) 200 WRITE(*,*) "-------------------------------" 201 ENDIF 202 ENDIF 203 204 END SUBROUTINE initracer2 205 206 FUNCTION indexOfTracer(name, sensitivity) RESULT(idx) 207 !! Get the index of a tracer by name. 208 !! 209 !! The function searches in the global tracer table (tracer_h:noms) 210 !! for the given name and returns the first index matching "name". 211 !! 212 !! If no name in the table matches the given one, -1 is returned ! 213 !! 214 !! @warning 215 !! initracers must be called before any use of this function. 216 IMPLICIT NONE 217 CHARACTER(len=*), INTENT(in) :: name !! Name of the tracer to search. 218 LOGICAL, OPTIONAL, INTENT(in) :: sensitivity !! Case sensitivity (true by default). 219 INTEGER :: idx !! Index of the first tracer matching name or -1 if not found. 220 LOGICAL :: zsens 221 INTEGER :: j 222 CHARACTER(len=LEN(name)) :: zname 223 zsens = .true. ; IF(PRESENT(sensitivity)) zsens = sensitivity 224 idx = -1 225 IF (.NOT.ALLOCATED(noms)) RETURN 226 IF (zsens) THEN 227 DO j=1,SIZE(noms) 228 IF (TRIM(noms(j)) == TRIM(name)) THEN 229 idx = j ; RETURN 230 ENDIF 231 ENDDO 232 ELSE 233 zname = to_lower(name) 234 DO j=1,SIZE(noms) 235 IF (TRIM(to_lower(noms(j))) == TRIM(zname)) THEN 236 idx = j ; RETURN 237 ENDIF 238 ENDDO 239 ENDIF 240 241 CONTAINS 242 243 FUNCTION to_lower(istr) RESULT(ostr) 244 !! Lower case conversion function. 245 IMPLICIT NONE 246 CHARACTER(len=*), INTENT(in) :: istr 247 CHARACTER(len=LEN(istr)) :: ostr 248 INTEGER :: i, ic 249 ostr = istr 250 DO i = 1, LEN_TRIM(istr) 251 ic = ICHAR(istr(i:i)) 252 IF (ic >= 65 .AND. ic < 90) ostr(i:i) = char(ic + 32) 253 ENDDO 254 END FUNCTION to_lower 255 END FUNCTION indexOfTracer 256 257 FUNCTION nameOfTracer(indx) RESULT(name) 258 !! Get the name of a tracer by index. 259 !! 260 !! The function searches in the global tracer table (tracer_h:noms) 261 !! and returns the name of the tracer at given index. 262 !! 263 !! If the index is out of range an empty string is returned. 264 !! 265 !! @warning 266 !! initracers must be called before any use of this function. 267 IMPLICIT NONE 268 INTEGER, INTENT(in) :: indx !! Index of the tracer name to retrieve. 269 CHARACTER(len=20) :: name !! Name of the tracer at given index. 270 name = '' 271 IF (.NOT.ALLOCATED(noms)) RETURN 272 IF (indx <= 0 .OR. indx > SIZE(noms)) RETURN 273 name = noms(indx) 274 END FUNCTION nameOfTracer 275 276 SUBROUTINE dumpTracers(indexes) 277 !! Print the names of the given list of tracers indexes. 278 INTEGER, DIMENSION(:), INTENT(in) :: indexes 279 INTEGER :: i,idx,nt 280 CHARACTER(len=:), ALLOCATABLE :: suffix 281 282 IF (.NOT.ALLOCATED(noms)) THEN 283 WRITE(*,'(a)') "[tracers_h:dump_tracers] warning: 'noms' is not allocated, tracers_h:initracer2 has not be called yet" 284 RETURN 285 ENDIF 286 nt = size(noms) 287 WRITE(*,"(a)") "local -> global : name" 288 DO i=1,size(indexes) 289 idx = indexes(i) 290 IF (idx < 1 .OR. idx >= nt) THEN 291 ! WRITE(*,'((a),I3,(a),I3,(a))') "index out of range (",idx,"/",nt,")" 292 CYCLE 293 ENDIF 294 IF (ANY(chimi_indx == idx)) THEN 295 suffix = ' (chimi)' 296 ELSE IF (ANY(micro_indx == idx)) THEN 297 suffix = ' (micro' 298 IF (ALLOCATED(ices_indx)) THEN 299 IF (ANY(ices_indx == idx)) suffix=suffix//", ice" 300 ENDIF 301 suffix=suffix//")" 302 ELSE 303 suffix=" ()" 304 ENDIF 305 WRITE(*,'(I5,(a),I6,(a))') i," -> ",idx ," : "//TRIM(noms(i))//suffix 306 ENDDO 307 END SUBROUTINE dumpTracers 308 309 310 END MODULE tracer_h 311
Note: See TracChangeset
for help on using the changeset viewer.