chemistry.F90 65 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720
  1. #define TRACEBACK write (gol,'("in ",a," (",a,i6,")")') rname, __FILE__, __LINE__ ; call goErr
  2. #define IF_NOTOK_RETURN(action) if (status/=0) then; TRACEBACK; action; return; end if
  3. #define IF_ERROR_RETURN(action) if (status> 0) then; TRACEBACK; action; return; end if
  4. !
  5. #include "tm5.inc"
  6. !
  7. !-----------------------------------------------------------------------------
  8. ! TM5 !
  9. !-----------------------------------------------------------------------------
  10. !BOP
  11. !
  12. ! !MODULE: CHEMISTRY
  13. !
  14. ! !DESCRIPTION: perform CBM4 chemistry simulation in TM5 + M7
  15. !\\
  16. !\\
  17. ! !INTERFACE:
  18. !
  19. MODULE CHEMISTRY
  20. !
  21. ! !USES:
  22. !
  23. use GO, only : gol, goErr, goPr, goBug
  24. use tm5_distgrid, only : dgrid, Get_DistGrid, gather
  25. use dims, only : nregions
  26. #ifdef with_budgets
  27. use budget_global, only : nbudg, nbud_vg
  28. use chem_param, only : ntrace, ntracet
  29. #endif
  30. IMPLICIT NONE
  31. PRIVATE
  32. !
  33. ! !PUBLIC MEMBER FUNCTIONS:
  34. !
  35. public :: Chemistry_Init, Chemistry_Done
  36. public :: Chemie
  37. !
  38. ! !PRIVATE DATA MEMBERS:
  39. !
  40. #ifdef with_budgets
  41. real, dimension(:,:,:), allocatable :: budchem
  42. real, Dimension(:,:,:), Allocatable :: budeqsam
  43. real :: eminox
  44. #ifdef with_m7
  45. real, dimension(:,:,:), allocatable :: budm7proc
  46. real, dimension(:,:,:), allocatable :: budm7
  47. #endif
  48. #endif
  49. character(len=*), parameter :: mname = 'chemistry'
  50. !
  51. ! minimal concentration required to apply scaling for slopes
  52. ! (to avoid floating point overflows):
  53. real, parameter :: eps = 1.0e-20
  54. !
  55. ! !REVISION HISTORY:
  56. ! 2005 - Elisabetta Vignati - changed for coupling with M7
  57. ! 22 Mar 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  58. !
  59. ! !REMARKS:
  60. !
  61. !EOP
  62. !------------------------------------------------------------------------
  63. CONTAINS
  64. !--------------------------------------------------------------------------
  65. ! TM5 !
  66. !--------------------------------------------------------------------------
  67. !BOP
  68. !
  69. ! !IROUTINE: CHEMISTRY_INIT
  70. !
  71. ! !DESCRIPTION: allocate and initialize budget arrays. Init M7 if needed.
  72. !\\
  73. !\\
  74. ! !INTERFACE:
  75. !
  76. SUBROUTINE CHEMISTRY_INIT( status )
  77. !
  78. ! !USES:
  79. !
  80. use Dims , only : nregions, im, jm, lm
  81. #ifdef with_budgets
  82. use Chem_param, only : ntrace, ntracet
  83. use ebischeme , only : sum_deposition, sum_wetchem, sum_chemistry
  84. use ebischeme , only : buddep_dat, budrrg, budrjg, budrwg
  85. !PLS use chem_param, only : ch4oh, so4pg, so4pa, o3p, o3l
  86. use chem_param, only : o3p, o3l
  87. #ifdef with_m7
  88. use m7_data, only : nm7procs
  89. #endif
  90. #endif
  91. #ifdef with_m7
  92. use mo_aero_m7, only : m7_initialize
  93. use m7_data, only : init_m7_data
  94. #endif
  95. use meteoData , only : Set
  96. use MeteoData , only : phlb_dat, m_dat, temper_dat, humid_dat, gph_dat
  97. use MeteoData , only : lwc_dat, iwc_dat, cc_dat
  98. !
  99. ! !OUTPUT PARAMETERS:
  100. !
  101. integer, intent(out) :: status
  102. !
  103. ! !REVISION HISTORY:
  104. ! 22 Mar 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  105. !
  106. !EOP
  107. !------------------------------------------------------------------------
  108. !BOC
  109. integer :: region, i1, i2, j1, j2
  110. character(len=*), parameter :: rname = mname//'/Chemistry_Init'
  111. ! --- begin --------------------------------
  112. ! select meteo to be used:
  113. do region = 1, nregions
  114. call Set( phlb_dat(region), status, used=.true. )
  115. call Set( m_dat(region), status, used=.true. )
  116. call Set( temper_dat(region), status, used=.true. )
  117. call Set( humid_dat(region), status, used=.true. )
  118. call Set( gph_dat(region), status, used=.true. )
  119. call Set( lwc_dat(region), status, used=.true. )
  120. call Set( iwc_dat(region), status, used=.true. )
  121. call Set( cc_dat(region), status, used=.true. )
  122. enddo
  123. #ifdef with_budgets
  124. do region = 1, nregions
  125. sum_chemistry (region) = 0.0
  126. sum_deposition(region) = 0.0
  127. sum_wetchem (region) = 0.0
  128. call Get_DistGrid( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
  129. allocate(buddep_dat(region)%dry(i1:i2, j1:j2, ntrace))
  130. buddep_dat(region)%dry = 0.0
  131. allocate(o3p(region)%d3(i1:i2, j1:j2, lm(region))); o3p(region)%d3 = 0.0
  132. allocate(o3l(region)%d3(i1:i2, j1:j2, lm(region))); o3l(region)%d3 = 0.0
  133. ! >>>
  134. ! TvN: still in sources_sinks.F90
  135. ! allocate(ch4oh(region)%d3(i1:i2, j1:j2, lm(region))); ch4oh(region)%d3 = 0.0
  136. ! allocate(so4pg(region)%d3(i1:i2, j1:j2, lm(region))); so4pg(region)%d3 = 0.0
  137. ! allocate(so4pa(region)%d3(i1:i2, j1:j2, lm(region))); so4pa(region)%d3 = 0.0
  138. ! <<<
  139. enddo
  140. budrrg = 0.0
  141. budrjg = 0.0
  142. budrwg = 0.0
  143. Allocate(budchem(nbudg,nbud_vg,ntrace))
  144. budchem = 0.0
  145. ! Two acid-base reactions
  146. Allocate(budeqsam(nbudg,nbud_vg,2))
  147. budeqsam = 0.0
  148. #ifdef with_m7
  149. ! M7 Bugets
  150. Allocate(budm7proc(nbudg,nbud_vg,nm7procs))
  151. Allocate(budm7(nbudg,nbud_vg,ntracet))
  152. budm7proc = 0.0
  153. budm7 = 0.0
  154. #endif
  155. ! global lightning NOx
  156. eminox = 0.
  157. #endif /* BUDGETS */
  158. #ifdef with_m7
  159. CALL M7_INITIALIZE
  160. CALL INIT_M7_DATA( status ) ! declare M7 output data structure
  161. IF_NOTOK_RETURN(status=1)
  162. #endif
  163. ! ok
  164. status = 0
  165. END SUBROUTINE CHEMISTRY_INIT
  166. !EOC
  167. !--------------------------------------------------------------------------
  168. ! TM5 !
  169. !--------------------------------------------------------------------------
  170. !BOP
  171. !
  172. ! !IROUTINE: CHEMISTRY_DONE
  173. !
  174. ! !DESCRIPTION: gather and write budgets
  175. !\\
  176. !\\
  177. ! !INTERFACE:
  178. !
  179. SUBROUTINE CHEMISTRY_DONE( status )
  180. !
  181. ! !USES:
  182. !
  183. use dims, only : nregions, im, jm, lm
  184. #ifdef with_budgets
  185. use dims, only : region_name
  186. use file_hdf, only : Init, Done, WriteAttribute, WriteData, SetDim, THdfFile, TSds
  187. use budget_global, only : budget_file_global, budg_dat, NHAB
  188. #ifndef without_boundary
  189. use boundary, only : budstratg
  190. #endif
  191. #ifndef without_emission
  192. use emission, only : budemig_all
  193. #endif
  194. use partools, only : isRoot, par_reduce_element, par_reduce
  195. use ebischeme, only : sum_deposition, sum_wetchem, sum_chemistry
  196. use ebischeme, only : buddep_dat, budrrg, budrjg, budrwg, budmarkg
  197. !PLS use chem_param, only : ch4oh, so4pg, so4pa, o3p, o3l, marknam, nmark
  198. use chem_param, only : o3p, o3l, marknam, nmark
  199. use chem_param, only : marknam, ntrace
  200. use chem_param, only : inox
  201. use reaction_data, only : nreac, ratnam, nreacw, rwnam
  202. use photolysis_data, only : nj, jnam
  203. #ifdef with_cariolle
  204. use chem_param, only : ncar, carnam
  205. use chemistry_cariolle, only : budcarg
  206. #endif
  207. #ifdef with_m7
  208. use m7_data, only : nm7procs
  209. #endif
  210. #endif /* BUDGETS */
  211. #ifdef with_m7
  212. use m7_data, only : free_m7_data
  213. #endif
  214. !
  215. ! !OUTPUT PARAMETERS:
  216. !
  217. integer, intent(out) :: status
  218. !
  219. ! !REVISION HISTORY:
  220. ! 22 Mar 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  221. !
  222. ! !REMARKS:
  223. !
  224. !EOP
  225. !------------------------------------------------------------------------
  226. !BOC
  227. character(len=*), parameter :: rname = mname//'/Chemistry_Done'
  228. integer :: region
  229. #ifdef with_budgets
  230. type(THdfFile) :: io
  231. type(TSds) :: sds
  232. real, dimension(:,:,:), allocatable :: collectb
  233. real,dimension(nbudg,nbud_vg,ntrace) :: buddry
  234. real,dimension(nbudg,nbud_vg,ntrace) :: budchem_result
  235. integer :: i, j, l, nzone, n, nsend, i1, i2, j1, j2
  236. ! for buggy MPI (see comment in budget_global.F90 for details)
  237. real, dimension(nregions) :: sum_chemistry_all, sum_wetchem_all, sum_deposition_all
  238. real, dimension(nbudg,nbud_vg,nreac) :: budrrg_all
  239. real, dimension(nbudg,nbud_vg,nj) :: budrjg_all
  240. real, dimension(nbudg,nbud_vg,nreacw) :: budrwg_all
  241. real, dimension(nbudg,nbud_vg,nmark) :: budmarkg_all
  242. real, dimension(nbudg,nbud_vg,ntrace) :: buddry_all
  243. real, dimension(nbudg,nbud_vg,ntrace) :: budchem_all
  244. real, dimension(nbudg,nbud_vg,2) :: budeqsam_all
  245. real :: eminox_all
  246. #ifndef without_boundary
  247. real, dimension(nbudg,nbud_vg,ntracet) :: budstratg_all
  248. #endif
  249. #ifdef with_cariolle
  250. real, dimension(nbudg,nbud_vg,ncar) :: budcarg_all
  251. #endif
  252. #ifdef with_m7
  253. real, dimension(nbudg,nbud_vg,ntracet) :: budm7_all
  254. real, dimension(nbudg,nbud_vg,nm7procs) :: budm7proc_all
  255. #endif
  256. #ifdef with_m7
  257. ! Do not change this order. And if you do, look through the M7 code to pprocess (parameter process) where it is written with a fixed paramter. You can, however, change this order if it is made dynamic.
  258. Character(len=8), Dimension(nm7procs), Parameter :: m7procnames = (/'NucN ','NucSU ','Coag11N ','Coag12N ','Coag12SU',&
  259. 'Coag13N ','Coag13SU','Coag14N ','Coag14SU','Coag15N ','Coag15SU','Coag16N ','Coag16SU','Coag17N ','Coag17SU',&
  260. 'Coag22N ','Coag23N ','Coag23SU','Coag23BC','Coag23OC','Coag24N ','Coag24SU','Coag24BC','Coag24OC','Coag25N ',&
  261. 'Coag25BC','Coag25OC','Coag26N ','Coag26SU','Coag26BC','Coag26OC','Coag27N ','Coag27SU','Coag27BC','Coag27OC',&
  262. 'Coag33N ','Coag35N ','Coag35BC','Coag35OC','Coag55N ','Cond1 ','Cond2 ','Cond3 ','Cond4 ','Cond5 ',&
  263. 'Cond6 ','Cond7 ','Age5N ','Age5BC ','Age5OC ','Age6N ','Age6DU ','Age7N ','Age7DU ','Grow1N ',&
  264. 'Grow1SU ','Grow2N ','Grow2SU ','Grow2BC ','Grow2OC ','Grow3N ','Grow3SU ','Grow3BC ','Grow3OC ','Grow3SS ','Grow3DU '/)
  265. ! Array for left hand sides, static attribute for the M7 process budget data set.
  266. Character(len=8), Dimension(nm7procs), Parameter :: m7proclhs = (/'void ','H2SO4 ','NUS_N ','NUS_N ','SO4NUS ',&
  267. 'NUS_N ','SO4NUS ','NUS_N ','SO4NUS ','NUS_N ','SO4NUS ','NUS_N ','SO4NUS ','NUS_N ','SO4NUS ',&
  268. 'AIS_N ','AIS_N ','SO4AIS ','BCAIS ','POMAIS ','AIS_N ','SO4AIS ','BCAIS ','POMAIS ','AII_N ',&
  269. 'BCAII ','POMAII ','AIS_N ','SO4AIS ','BCAIS ','POMAIS ','AIS_N ','SO4AIS ','BCAIS ','POMAIS ',&
  270. 'ACS_N ','AII_N ','BCAII ','POMAII ','AII_N ','H2SO4 ','H2SO4 ','H2SO4 ','H2SO4 ','H2SO4 ',&
  271. 'H2SO4 ','H2SO4 ','AII_N ','BCAII ','POMAII ','ACI_N ','DUACI ','COI_N ','DUCOI ','NUS_N ',&
  272. 'SO4NUS ','AIS_N ','SO4AIS ','BCAIS ','POMAIS ','ACS_N ','SO4ACS ','BCACS ','POMACS ','SSACS ','DUACS '/)
  273. ! Array for right hand sides, static attribute for the M7 process budget data set.
  274. Character(len=8), Dimension(nm7procs), Parameter :: m7procrhs = (/'NUS_N ','SO4NUS ','void ','void ','SO4AIS ',&
  275. 'void ','SO4ACS ','void ','SO4COS ','void ','SO4AIS ','void ','SO4ACS ','void ','SO4COS ',&
  276. 'void ','void ','SO4ACS ','BCACS ','POMACS ','void ','SO4COS ','BCCOS ','POMCOS ','void ',&
  277. 'BCAIS ','POMAIS ','void ','SO4ACS ','BCACS ','POMACS ','void ','SO4COS ','BCCOS ','POMCOS ',&
  278. 'void ','void ','BCACS ','POMACS ','void ','SO4NUS ','SO4AIS ','SO4ACS ','SO4COS ','SO4AIS ',&
  279. 'SO4ACS ','SO4COS ','AIS_N ','BCAIS ','POMAIS ','ACS_N ','DUACS ','COS_N ','DUCOS ','AIS_N ',&
  280. 'SO4AIS ','ACS_N ','SO4ACS ','BCACS ','POMACS ','COS_N ','SO4COS ','BCCOS ','POMCOS ','SSCOS ','DUCOS '/)
  281. #endif
  282. #endif /* BUDGETS */
  283. ! --- begin --------------------------------
  284. #ifdef with_budgets
  285. ! Sum up contribution from each proc into root array
  286. call PAR_REDUCE_ELEMENT(budrrg, 'SUM', budrrg_all, status )
  287. do region = 1, nregions
  288. CALL PAR_REDUCE(sum_chemistry(region), 'SUM', sum_chemistry_all(region), status)
  289. IF_NOTOK_RETURN(status=1)
  290. CALL PAR_REDUCE(sum_deposition(region), 'SUM', sum_deposition_all(region), status)
  291. IF_NOTOK_RETURN(status=1)
  292. CALL PAR_REDUCE(sum_wetchem(region), 'SUM', sum_wetchem_all(region), status)
  293. IF_NOTOK_RETURN(status=1)
  294. end do
  295. ! Sum up contribution from each proc into root array for "total LiNOx"
  296. call PAR_REDUCE( eminox, 'SUM', eminox_all, status )
  297. eminox_all = eminox_all*1.e-9 ! kg -> Tg
  298. if ( isRoot ) then
  299. call Init(io, budget_file_global, 'write', status)
  300. IF_NOTOK_RETURN(status=1)
  301. call WriteAttribute(io, 'sum_chemistry' , sum_chemistry_all, status)
  302. IF_NOTOK_RETURN(status=1)
  303. call WriteAttribute(io, 'sum_wetchem' , sum_wetchem_all, status)
  304. IF_NOTOK_RETURN(status=1)
  305. call WriteAttribute(io, 'sum_deposition' , sum_deposition_all, status)
  306. IF_NOTOK_RETURN(status=1)
  307. call WriteAttribute(io, 'total_lightning_nox_emissions_Tg_N' , eminox_all, status)
  308. IF_NOTOK_RETURN(status=1)
  309. call Init(Sds, io, 'budrr', (/nbudg,nbud_vg,nreac/), 'real(8)', status)
  310. IF_NOTOK_RETURN(status=1)
  311. call WriteAttribute(Sds, 'ratnam', ratnam, status)
  312. IF_NOTOK_RETURN(status=1)
  313. call SetDim(Sds, 0, 'nbudg', 'horizontal region', (/(j, j=1,nbudg)/), status)
  314. call SetDim(Sds, 1, 'nbud_vg','vertical layer', (/(j, j=1,nbud_vg)/), status)
  315. call SetDim(Sds, 2, 'nreac', 'reaction number', (/(j, j=1,nreac)/), status)
  316. IF_NOTOK_RETURN(status=1)
  317. call WriteData(Sds, BUDRRG_all, status)
  318. IF_NOTOK_RETURN(status=1)
  319. call Done(Sds, status)
  320. IF_NOTOK_RETURN(status=1)
  321. end if
  322. ! Sum up contribution from each proc into root array
  323. call PAR_REDUCE_ELEMENT(budrjg, 'SUM', budrjg_all, status )
  324. if ( isRoot ) then
  325. call Init(Sds,io, 'budrj',(/nbudg,nbud_vg,nj/), 'real(8)', status)
  326. IF_NOTOK_RETURN(status=1)
  327. call WriteAttribute(Sds, 'jnam', jnam, status)
  328. IF_NOTOK_RETURN(status=1)
  329. call SetDim(Sds, 0, 'nbudg','horizontal region', (/(j, j=1,nbudg)/), status)
  330. call SetDim(Sds, 1, 'nbud_vg','vertical layer', (/(j, j=1,nbud_vg)/), status)
  331. call SetDim(Sds, 2, 'nj','reaction number', (/(j, j=1,nj)/), status)
  332. IF_NOTOK_RETURN(status=1)
  333. call WriteData(Sds, BUDRJG_all, status)
  334. IF_NOTOK_RETURN(status=1)
  335. call Done(Sds, status)
  336. IF_NOTOK_RETURN(status=1)
  337. end if
  338. ! Lets us write down the WET CHEMISTRY
  339. call PAR_REDUCE_ELEMENT(budrwg, 'SUM', budrwg_all, status )
  340. if ( isRoot ) then
  341. call Init(Sds,io, 'budrw',(/nbudg,nbud_vg,nreacw/), 'real(8)', status)
  342. IF_NOTOK_RETURN(status=1)
  343. call WriteAttribute(Sds, 'rwnam', rwnam, status)
  344. IF_NOTOK_RETURN(status=1)
  345. call SetDim(Sds, 0, 'nbudg','horizontal region', (/(j, j=1,nbudg)/), status)
  346. call SetDim(Sds, 1, 'nbud_vg','vertical layer', (/(j, j=1,nbud_vg)/), status)
  347. call SetDim(Sds, 2, 'nreacw','wet reaction number', (/(j, j=1,nreacw)/), status)
  348. IF_NOTOK_RETURN(status=1)
  349. call WriteData(Sds, BUDRWG_all, status)
  350. IF_NOTOK_RETURN(status=1)
  351. call Done(Sds, status)
  352. IF_NOTOK_RETURN(status=1)
  353. end if
  354. ! Sum up contribution from each proc into root array
  355. call PAR_REDUCE_ELEMENT(budmarkg, 'SUM', budmarkg_all, status )
  356. if ( isRoot ) then
  357. call Init(Sds,io, 'budmark',(/nbudg,nbud_vg,nmark/), 'real(8)', status)
  358. IF_NOTOK_RETURN(status=1)
  359. call WriteAttribute(Sds, 'marknam', marknam, status)
  360. IF_NOTOK_RETURN(status=1)
  361. call SetDim(Sds, 0, 'nbudg','horizontal region', (/(j, j=1,nbudg)/), status)
  362. call SetDim(Sds, 1, 'nbud_vg','vertical layer', (/(j, j=1,nbud_vg)/), status)
  363. call SetDim(Sds, 2, 'nmark','marked tracer number', (/(j, j=1,nmark)/), status)
  364. IF_NOTOK_RETURN(status=1)
  365. call WriteData(Sds, BUDMARKG_all, status)
  366. IF_NOTOK_RETURN(status=1)
  367. call Done(Sds, status)
  368. IF_NOTOK_RETURN(status=1)
  369. end if
  370. ! DRYDEP budget
  371. buddry = 0.0
  372. do region=1,nregions
  373. ! aggregates horizontally budget
  374. call Get_DistGrid( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
  375. do n=1,ntrace
  376. do j=j1,j2
  377. do i=i1,i2
  378. nzone = budg_dat(region)%nzong(i,j)
  379. buddry(nzone,1,n) = buddry(nzone,1,n) + buddep_dat(region)%dry(i,j,n)
  380. end do
  381. end do
  382. end do
  383. call PAR_REDUCE_ELEMENT(buddry, 'SUM', buddry_all, status ) ! contribution from all procs
  384. ! gather and write Non-Horizontally-Aggregated-Budgets
  385. if (NHAB) then
  386. if ( isRoot ) then
  387. allocate( collectb(im(region),jm(region),ntrace ))
  388. else
  389. allocate( collectb(1,1,1))
  390. end if
  391. call GATHER( dgrid(region), buddep_dat(region)%dry, collectb, 0, status)
  392. if(isRoot) then
  393. call Init(Sds,io, 'buddep_dat_dry_'//region_name(region),(/im(region),jm(region),ntrace/), 'real(4)', status)
  394. call SetDim(Sds, 0, 'im_'//region_name(region),'longitude', (/(j, j=1,im(region))/), status)
  395. call SetDim(Sds, 1, 'jm_'//region_name(region),'latitude', (/(j, j=1,jm(region))/), status)
  396. call SetDim(Sds, 2, 'ntrace','tracer index', (/(j, j=1,ntrace)/), status)
  397. IF_NOTOK_RETURN(status=1)
  398. call WriteData(Sds, collectb, status)
  399. IF_NOTOK_RETURN(status=1)
  400. call Done(Sds, status)
  401. IF_NOTOK_RETURN(status=1)
  402. endif
  403. deallocate(collectb)
  404. endif ! NHAB
  405. enddo ! regions
  406. !-- write more aggregated budgets
  407. call PAR_REDUCE_ELEMENT(budchem, 'SUM', budchem_all, status )
  408. call PAR_REDUCE_ELEMENT(budeqsam, 'SUM', budeqsam_all, status )
  409. #ifndef without_boundary
  410. call PAR_REDUCE_ELEMENT(budstratg,'SUM', budstratg_all, status )
  411. #endif
  412. #ifdef with_m7
  413. call PAR_REDUCE_ELEMENT(budm7, 'SUM', budm7_all, status )
  414. call PAR_REDUCE_ELEMENT(budm7proc,'SUM', budm7proc_all, status )
  415. #endif
  416. if(isRoot) then
  417. call Init(Sds,io, 'buddry',(/nbudg,nbud_vg,ntrace/), 'real(8)', status)
  418. IF_NOTOK_RETURN(status=1)
  419. call SetDim(Sds, 0, 'nbudg','horizontal region', (/(j, j=1,nbudg)/), status)
  420. call SetDim(Sds, 1, 'nbud_vg','vertical layer', (/(j, j=1,nbud_vg)/), status)
  421. call SetDim(Sds, 2, 'ntrace','tracer index', (/(j, j=1,ntrace)/), status)
  422. IF_NOTOK_RETURN(status=1)
  423. call WriteData(Sds,buddry_all,status)
  424. IF_NOTOK_RETURN(status=1)
  425. call Done(Sds, status)
  426. IF_NOTOK_RETURN(status=1)
  427. Call Init(Sds,io,"budchem",(/nbudg,nbud_vg,ntrace/),'real(8)',status)
  428. call SetDim(Sds, 0, 'nbudg','horizontal budget', (/(j, j=1,nbudg)/), status)
  429. call SetDim(Sds, 1, 'nbud_vg','vertical budget', (/(j, j=1,nbud_vg)/), status)
  430. call SetDim(Sds, 2, 'ntrace','tracer number', (/(j, j=1,ntrace)/), status)
  431. IF_NOTOK_RETURN(status=1)
  432. call WriteAttribute(Sds, 'comment', 'EBI budget stuffed together. Hopefully it does not explode', status)
  433. ! correct chemistry budget
  434. budchem_result = budchem_all+buddry_all
  435. #ifndef without_emission
  436. budchem_result(:,:,inox) = budchem_result(:,:,inox) - budemig_all(:,:,inox)
  437. #endif
  438. call WriteData(Sds,budchem_result,status)
  439. IF_NOTOK_RETURN(status=1)
  440. call Done(Sds, status)
  441. IF_NOTOK_RETURN(status=1)
  442. Call Init(Sds,io,"budeqsam",(/nbudg,nbud_vg,2/),'real(8)',status)
  443. call SetDim(Sds, 0, 'nbudg','horizontal budget', (/(j, j=1,nbudg)/), status)
  444. call SetDim(Sds, 1, 'nbud_vg','vertical budget', (/(j, j=1,nbud_vg)/), status)
  445. call SetDim(Sds, 2, 'AB_reac','Acid-base reaction number', (/(j, j=1,2)/), status)
  446. IF_NOTOK_RETURN(status=1)
  447. call WriteAttribute(Sds, 'comment', 'EQSAM evil acid base reaction. Positive forms aerosol material.', status)
  448. call WriteData(Sds,budeqsam_all,status)
  449. IF_NOTOK_RETURN(status=1)
  450. call Done(Sds, status)
  451. IF_NOTOK_RETURN(status=1)
  452. #ifndef without_boundary
  453. Call Init(Sds,io,"budstrat",(/nbudg,nbud_vg,ntracet/),'real(8)',status)
  454. call SetDim(Sds, 0, 'nbudg','horizontal budget', (/(j, j=1,nbudg)/), status)
  455. call SetDim(Sds, 1, 'nbud_vg','vertical budget', (/(j, j=1,nbud_vg)/), status)
  456. call SetDim(Sds, 2, 'ntracet','tracer number', (/(j, j=1,ntracet)/), status)
  457. IF_NOTOK_RETURN(status=1)
  458. call WriteAttribute(Sds, 'comment', 'Stratosphere (from boundary.F90)', status)
  459. call WriteData(Sds,budstratg_all,status)
  460. IF_NOTOK_RETURN(status=1)
  461. call Done(Sds, status)
  462. IF_NOTOK_RETURN(status=1)
  463. #endif
  464. endif
  465. #ifdef with_cariolle
  466. call PAR_REDUCE_ELEMENT(budcarg, 'SUM', budcarg_all, status )
  467. if ( isRoot ) then
  468. call Init(Sds,io, 'budcar',(/nbudg,nbud_vg,ncar/), 'real(8)', status)
  469. IF_NOTOK_RETURN(status=1)
  470. call WriteAttribute(Sds, 'carnam', carnam, status)
  471. IF_NOTOK_RETURN(status=1)
  472. call SetDim(Sds, 0, 'nbudg','horizontal region', (/(j, j=1,nbudg)/), status)
  473. call SetDim(Sds, 1, 'nbud_vg','vertical layer', (/(j, j=1,nbud_vg)/), status)
  474. call SetDim(Sds, 2, 'ncar','Cariolle tracer number', (/(j, j=1,ncar)/), status)
  475. IF_NOTOK_RETURN(status=1)
  476. call WriteData(Sds,budcarg_all,status)
  477. IF_NOTOK_RETURN(status=1)
  478. call Done(Sds, status)
  479. IF_NOTOK_RETURN(status=1)
  480. end if
  481. #endif
  482. #ifdef with_m7
  483. if ( isRoot ) then
  484. ! M7 process budget
  485. Call Init(Sds,io,"budm7proc",(/nbudg,nbud_vg,nm7procs/),'real(8)',status)
  486. call SetDim(Sds, 0, 'nbudg','horizontal budget', (/(j, j=1,nbudg)/), status)
  487. call SetDim(Sds, 1, 'nbud_vg','vertical budget', (/(j, j=1,nbud_vg)/), status)
  488. call SetDim(Sds, 2, 'nm7proc','M7 process number', (/(j, j=1,nm7procs)/), status)
  489. IF_NOTOK_RETURN(status=1)
  490. call WriteAttribute(Sds, 'procnames',m7procnames, status)
  491. call WriteAttribute(Sds, 'lefthandsides',m7proclhs, status)
  492. call WriteAttribute(Sds, 'righthandsides',m7procrhs, status)
  493. call WriteData(Sds,budm7proc_all,status)
  494. IF_NOTOK_RETURN(status=1)
  495. call Done(Sds, status)
  496. IF_NOTOK_RETURN(status=1)
  497. ! M7 budget
  498. Call Init(Sds,io,"budm7",(/nbudg,nbud_vg,ntracet/),'real(8)',status)
  499. call SetDim(Sds, 0, 'nbudg','horizontal budget', (/(j, j=1,nbudg)/), status)
  500. call SetDim(Sds, 1, 'nbud_vg','vertical budget', (/(j, j=1,nbud_vg)/), status)
  501. call SetDim(Sds, 2, 'ntracet','tracer number', (/(j, j=1,ntracet)/), status)
  502. IF_NOTOK_RETURN(status=1)
  503. call WriteAttribute(Sds, 'comment', 'M7 budget stuffed together. Hopefully the M7 tracers have now correct budgets', status)
  504. call WriteData(Sds,budm7_all,status)
  505. IF_NOTOK_RETURN(status=1)
  506. call Done(Sds, status)
  507. IF_NOTOK_RETURN(status=1)
  508. endif
  509. #endif
  510. if ( isRoot ) then
  511. call Done(io, status)
  512. IF_NOTOK_RETURN(status=1)
  513. endif
  514. do region = 1, nregions
  515. deallocate(buddep_dat(region)%dry)
  516. deallocate(o3p(region)%d3)
  517. deallocate(o3l(region)%d3)
  518. enddo
  519. deallocate(budchem)
  520. deallocate(budeqsam)
  521. #ifdef with_m7
  522. deallocate(budm7proc)
  523. deallocate(budm7)
  524. #endif
  525. #endif /* BUDGETS */
  526. #ifdef with_m7
  527. call free_m7_data
  528. #endif
  529. ! ok
  530. status = 0
  531. END SUBROUTINE CHEMISTRY_DONE
  532. !EOC
  533. !--------------------------------------------------------------------------
  534. ! TM5 !
  535. !--------------------------------------------------------------------------
  536. !BOP
  537. !
  538. ! !IROUTINE: CHEMIE
  539. !
  540. ! !DESCRIPTION: performs chemistry transformations of the tracers
  541. !\\
  542. !\\
  543. ! !INTERFACE:
  544. !
  545. SUBROUTINE CHEMIE( region, tr, status )
  546. !
  547. ! !USES:
  548. !
  549. use GO, only : TDate
  550. use binas, only : Avog, pi, xmair, Rgas_air
  551. use dims, only : itaur, nchem, tref, sec_month, revert, okdebug
  552. use dims, only : dx, xref, dy, yref, im, jm, lm
  553. use dims, only : nregions, ndyn, ndyn_max
  554. use dims, only : xbeg, ybeg, adv_scheme, mlen
  555. use chem_param, only : xmbc, xmpom, xmnacl, xmdust !EV
  556. use chem_param, only : maxtrace, n_extra, iso4, ino3_a, inh4, ih2opart
  557. use chem_param, only : irinc, ino, xmn, inox, ieno, iairm, iairn, ntrace
  558. use chem_param, only : ntracet, fscale, imsa, iacid, iair, ih2o, io2, ih2on
  559. use chem_param, only : iairm,i_temp, i_pres, inh3, ihno3, xmh2o, names
  560. #ifdef with_m7
  561. use chem_param, only : iso4nus, iso4ais, iso4acs, iso4cos, ibcais, ibcacs, ibccos, ibcaii, ipomais, ipomacs
  562. use chem_param, only : ipomcos, ipomaii, issacs, isscos, iduacs, iducos, iduaci,iducoi
  563. use chem_param, only : inus_n, xmnumb, iais_n, iacs_n, icos_n, iaii_n, iaci_n, icoi_n
  564. use chem_param, only : nh4no3_factor, nh4no3_density, msa_density
  565. use mo_aero_m7, only : cmr2ram, ram2cmr
  566. use binas, only : rol
  567. #endif
  568. use chem_param, only : idz
  569. use meteodata, only : m_dat, gph_dat
  570. use reaction_data, only : nreac, aerdens, kn2o5aq
  571. use chem_rates, only : calrates
  572. use eqsam_param, only : eqsam_v03d
  573. use toolbox, only : dumpfield
  574. use datetime, only : tau2date, get_day
  575. use global_data, only : region_dat, mass_dat, chem_dat
  576. #ifndef without_photolysis
  577. #ifdef with_optics
  578. use photolysis, only : aerosol_info_m7
  579. #else
  580. use photolysis, only : aerosol_info
  581. #endif
  582. use photolysis, only : daysim, get_sza, photo_flux
  583. use photolysis_data
  584. #endif
  585. use ebischeme, only : ebi
  586. #ifndef without_emission
  587. use dims, only : at, bt
  588. use emission_nox, only : eminox_lightning, nox_emis_3d
  589. use emission_nox, only : nox_emis_3d_bb_app, emission_nox_bb_daily_cycle
  590. #endif
  591. #ifdef with_budgets
  592. use emission_data, only : budemi_dat, sum_emission
  593. use budget_global, only : budg_dat, nzon_vg
  594. #endif
  595. #ifndef without_sedimentation
  596. use sedimentation, only : rh
  597. #endif
  598. #ifdef with_cariolle
  599. use chem_param, only : io3
  600. use chemistry_cariolle, only : l_cariolle, with_trop_force
  601. #endif
  602. ! use tracer_data, only : tracer_print ! for debugging
  603. #ifdef with_m7
  604. use mo_aero_m7, only : naermod, nmod, nsol
  605. use m7_data, only : rw_mode, rwd_mode, dens_mode, h2o_mode
  606. !use emission_data, only : oc2pom !factor for conversion of OC mass to POM
  607. #ifdef with_budgets
  608. Use m7_data, only : nm7procs
  609. #endif
  610. !#ifdef with_optics
  611. ! Use Optics, only : nwl, aod_count, AOD, calculate_aop
  612. ! Use chem_param, only : xmso4, xmno3
  613. !#endif
  614. external :: m7
  615. #endif /* M7 */
  616. !
  617. ! !INPUT PARAMETERS:
  618. !
  619. integer, intent(in) :: region
  620. type(TDate), intent(in) :: tr(2)
  621. !
  622. ! !OUTPUT PARAMETERS:
  623. !
  624. integer, intent(out) :: status
  625. !
  626. ! !REVISION HISTORY:
  627. ! 22 Mar 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  628. !
  629. !EOP
  630. !------------------------------------------------------------------------
  631. !BOC
  632. character(len=*), parameter :: rname = mname//'/chemie'
  633. ! --- local ------------------------------
  634. real,dimension(:,:,:),pointer :: m
  635. real,dimension(:,:,:,:),pointer :: rm
  636. #ifdef slopes
  637. real,dimension(:,:,:,:),pointer :: rxm, rym, rzm
  638. #ifdef secmom
  639. real,dimension(:,:,:,:),pointer :: rxxm, rxym, rxzm, ryym, ryzm, rzzm
  640. #endif
  641. #endif
  642. real,dimension(:,:,:,:),pointer :: rmc
  643. real,dimension(:,:,:),pointer :: r_cloud
  644. ! store per level actinic fluxes, photolysis rates, and reaction rates
  645. #ifndef without_photolysis
  646. real,dimension(:,:,:),allocatable :: fact
  647. #endif
  648. real,dimension(:,:,:),allocatable :: rj, rr
  649. ! new photolysis array
  650. real,dimension(:,:,:,:),allocatable :: rj_new
  651. ! store concentrations for chemistry ....
  652. real,dimension(:,:,:),allocatable :: y, y0, yhelp
  653. ! store information that is transferred
  654. ! between chemistry modules
  655. real,dimension(:,:,:),allocatable :: ye
  656. real,dimension(:,:), allocatable :: th, tha, sza, mu, reff
  657. real :: starttime,deltat
  658. ! eqsam:
  659. real,dimension(:,:), allocatable :: yi, yo
  660. ! sad:
  661. real,dimension(:,:,:), allocatable :: sad_aer_out, sad_cld_out, sad_ice_out
  662. #ifdef with_m7
  663. ! m7:
  664. real, dimension(:), pointer :: dxyp
  665. real, dimension(:,:), allocatable :: presm7, rhm7, tempm7, dryairm7 ! meteo parameters
  666. real, dimension(:,:), allocatable :: h2so4m7 ! h2so4 gas phase
  667. real, dimension(:,:,:), allocatable :: aemassm7 ! aerosol mass
  668. real, dimension(:,:,:), allocatable :: aenumm7 ! aerosol number
  669. !#ifdef with_optics
  670. ! Integer :: iband
  671. ! real,dimension(:,:,:),allocatable :: Ext ! extinction coefficient [1/m]
  672. ! real,dimension(:,:,:),allocatable :: a ! single-scattering albedo [unitless]
  673. ! real,dimension(:,:,:),allocatable :: g ! asymmetry parameter [unitless]
  674. !#endif
  675. real, dimension(:,:,:), allocatable :: aedensm7 ! aerosol density
  676. real, dimension(:,:,:), allocatable :: aewatm7 ! aerosol water content
  677. real, dimension(:,:,:), allocatable :: aeradm7 ! aerosol radius in equilibrium with water
  678. real, dimension(:,:,:), allocatable :: aeradrm7 ! aerosol dry radius
  679. !
  680. ! To convert units from M7 to TM5 units
  681. real, parameter :: convnumb = 1.e3/xmnumb*Avog ! This value is needed directly
  682. real, parameter :: convsu = 1. ! Nothing happens for sulfate.
  683. real, parameter :: convbc = 1e-12/xmbc*Avog ! BC
  684. !>>> TvN
  685. ! I have the impression that OC in M7 actually refers to POM.
  686. ! doc seems to be the density of POM not OC, and is equal to the density of BC (dbc).
  687. ! Compare with GLOMAP, where the densities of POM and BC are the same (Mann et al., GMD, 2010).
  688. ! This would imply that also the mass of POM and not OC should be used in M7,
  689. ! and that "OC" in the paper by Vignati et al. (JGR, 2004) is actually referring to POM,
  690. ! consistent with the terminology used by Stier et al. (ACP, 2005).
  691. !real, parameter :: convoc = 1e-12/xmpom*Avog*oc2pom ! OC (M7) POM (TM5)
  692. real, parameter :: convoc = 1e-12/xmpom*Avog ! POM (in both M7 and TM5)
  693. !<<< TvN
  694. real, parameter :: convss = 1e-12/xmnacl*Avog ! SS
  695. real, parameter :: convdu = 1e-12/xmdust*Avog ! DU
  696. #ifdef with_budgets
  697. real,dimension(:,:,:), allocatable :: processm7 ! M7 processes in M7 units.
  698. ! Array that convertts M7 processes from M7 to TM5 units.
  699. real, dimension(nm7procs), parameter :: processm7totm5 = (/ &
  700. ! 1 2 3 4 5 6 7 8 9 10
  701. convnumb,convsu ,convnumb,convnumb,convsu ,convnumb,convsu ,convnumb,convsu,convnumb,& ! 0?
  702. convsu ,convnumb,convsu ,convnumb,convsu ,convnumb,convnumb,convsu ,convbc,convoc ,& ! 1?
  703. convnumb,convsu ,convbc ,convoc ,convnumb,convbc ,convoc ,convnumb,convsu,convbc ,& ! 2?
  704. convoc ,convnumb,convsu ,convbc ,convoc ,convnumb,convnumb,convbc ,convoc,convnumb,& ! 3?
  705. convsu ,convsu ,convsu ,convsu ,convsu ,convsu ,convsu ,convnumb,convbc,convoc ,& ! 4?
  706. convnumb,convdu ,convnumb,convdu ,convnumb,convsu ,convnumb,convsu ,convbc,convoc ,& ! 5?
  707. convnumb,convsu ,convbc ,convoc ,convss ,convdu /)
  708. #endif
  709. real :: dryvol_m7, vol_nh4no3, vol_msa, vol_h2o
  710. real :: number_conc
  711. integer :: imode
  712. #endif /* M7 */
  713. real :: dtime, gmt, dxx, dyy, lat, lon
  714. real :: px, skf, x, month2dt
  715. integer :: day, level, nzone, nzone_v
  716. integer,dimension(6) :: idater, idate_temp
  717. integer :: i, j, l, n
  718. integer :: ispec
  719. integer :: imax, nca, nco, iloop
  720. integer :: eqsam_option
  721. real :: dry_aerosol_mass, dry_aerosol_volume
  722. real :: water_aerosol_mass, water_aerosol_volume, ccs, s
  723. integer :: i1, i2, j1, j2, lmr, is3, ie3, klm
  724. ! --- begin ---------------------------------
  725. if ( okdebug ) write (*,*) 'start of chemistry'
  726. m => m_dat (region)%data
  727. rmc => chem_dat(region)%rm
  728. rm => mass_dat(region)%rm
  729. #ifdef slopes
  730. rxm => mass_dat(region)%rxm
  731. rym => mass_dat(region)%rym
  732. rzm => mass_dat(region)%rzm
  733. #ifdef secmom
  734. rxxm => mass_dat(region)%rxxm
  735. rxym => mass_dat(region)%rxym
  736. rxzm => mass_dat(region)%rxzm
  737. ryym => mass_dat(region)%ryym
  738. ryzm => mass_dat(region)%ryzm
  739. rzzm => mass_dat(region)%rzzm
  740. #endif
  741. #endif
  742. #ifdef with_m7
  743. dxyp => region_dat(region)%dxyp
  744. #endif
  745. r_cloud => phot_dat(region)%cloud_reff
  746. ! ------- Time stuff
  747. call tau2date(itaur(region), idater) ! current time
  748. dtime = nchem/(2*tref(region)) ! time step
  749. month2dt = dtime/sec_month ! conversion to emission per timestep
  750. call tau2date(itaur(region)+revert*nint(dtime*0.5),idate_temp) ! get date @ halfway interval.
  751. gmt = idate_temp(4) + idate_temp(5)/60.0 + idate_temp(6)/3600.0 ! GMT in hours
  752. day = get_day(idate_temp(2),idate_temp(3),mlen)
  753. if ( okdebug ) then
  754. write(gol,*)'chemistry: region ',region, ' at date: ',idater,' with time step ',dtime
  755. call goPr
  756. write(gol,*)'chemistry: day, gmt, date@halfway interval ', day, gmt, idate_temp
  757. call goPr
  758. end if
  759. ! ------- Resolution and bounds
  760. dxx = dx/xref(region) ! gridsize at current region
  761. dyy = dy/yref(region) ! gridsize at current region
  762. call Get_DistGrid( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
  763. lmr = lm(region)
  764. is3=(i1-1)*3+1 ! to cover three times oversampled
  765. ie3=i2*3
  766. ! allocate(tha (is3:ie3,j1:j2))
  767. allocate(tha (im(region)*3,j1:j2))
  768. allocate(sza (i1:i2, j1:j2 ))
  769. allocate(mu (i1:i2, j1:j2 ))
  770. allocate(reff (i1:i2, j1:j2 ))
  771. allocate(fact (i1:i2, j1:j2, nbands_trop ))
  772. allocate(rj (i1:i2, j1:j2, nj ))
  773. allocate(rr (i1:i2, j1:j2, nreac ))
  774. allocate(rj_new(i1:i2, j1:j2, lmr, nj ))
  775. allocate(y (i1:i2, j1:j2, maxtrace ))
  776. allocate(y0 (i1:i2, j1:j2, maxtrace ))
  777. allocate(yhelp (i1:i2, j1:j2, ntrace ))
  778. allocate(ye (i1:i2, j1:j2, n_extra )) ! Eqsam
  779. allocate(sad_cld_out(i1:i2, j1:j2, lmr )) ; sad_cld_out = 0.
  780. allocate(sad_ice_out(i1:i2, j1:j2, lmr )) ; sad_ice_out = 0.
  781. allocate(sad_aer_out(i1:i2, j1:j2, lmr )) ; sad_aer_out = 0.
  782. imax = (i2-i1+1)*(j2-j1+1) !nb of grid box per layer (was im(region)*jm(region))
  783. nca = 11
  784. nco = 37 ! was 36, JadB added one for the water associated with just the nitrate.
  785. allocate(yi(imax,nca)) ; yi = 0.0
  786. allocate(yo(imax,nco)) ; yo = 0.0
  787. #ifdef with_m7
  788. allocate( presm7 (imax, 1 ))
  789. allocate( rhm7 (imax, 1 ))
  790. allocate( tempm7 (imax, 1 ))
  791. allocate( dryairm7(imax, 1 ))
  792. allocate( h2so4m7 (imax, 1 ))
  793. allocate( aemassm7(imax, 1, naermod))
  794. allocate( aenumm7 (imax, 1, nmod ))
  795. allocate( aedensm7(imax,1,nmod))
  796. allocate( aewatm7 (imax,1,nmod))
  797. allocate( aeradm7 (imax,1,nmod))
  798. allocate( aeradrm7(imax,1,nsol))
  799. !PLS debug
  800. presm7 =0.
  801. rhm7 =0.
  802. tempm7 =0.
  803. dryairm7=0.
  804. h2so4m7 =0.
  805. aemassm7=0.
  806. aenumm7 =0.
  807. aedensm7=0.
  808. aewatm7 =0.
  809. aeradm7 =0.
  810. aeradrm7=0.
  811. #ifdef with_budgets
  812. allocate(processm7(imax,1,nm7procs))
  813. #endif
  814. #endif
  815. tha = 0.0
  816. sza = 0.0
  817. mu = 0.0
  818. fact = 0.0
  819. rj = 0.0
  820. rr = 0.0
  821. rj_new = 0.0
  822. y = 0.0
  823. y0 = 0.0
  824. ye = 0.0
  825. ! alternative calculation of zenith angle with higher sampling (time and space).
  826. ! yields factor of two lower angles in the tropics!
  827. ! Difference is resolution dependent. The coarser the larger the differences
  828. starttime = real(idate_temp(4)) + real(idate_temp(5))/60.0 + real(idate_temp(6))/3600.
  829. deltat = nchem/3600.0
  830. call daysim(region, day, is3, i1,i2,j1, j2, tha)
  831. call get_sza(region, i1, j1, i2, j2, starttime, deltat, tha, sza)
  832. ! ascribe mu
  833. do j=j1,j2
  834. do i=i1,i2
  835. mu(i,j)=max(1.e-5,COS(sza(i,j)*pi/180.))
  836. enddo
  837. enddo
  838. #ifdef with_optics
  839. call aerosol_info_m7(region, status)
  840. IF_NOTOK_RETURN(status=1)
  841. #else
  842. call aerosol_info(region)
  843. #endif
  844. ! calculate actinic flux outside level loop for online fluxes
  845. call photo_flux(region, i1, j1, sza, rj_new)
  846. ! scale NOx BMB if needed
  847. #ifndef without_emission
  848. call emission_nox_bb_daily_cycle(status)
  849. IF_NOTOK_RETURN(status=1)
  850. #endif
  851. ! compute global LiNox budget
  852. #ifdef with_budgets
  853. #ifndef without_emission
  854. #ifndef without_convection
  855. eminox=eminox+sum(eminox_lightning(region)%d3)*month2dt ! kg [N] month-1 * dt /(sec_month) = kg [N]
  856. #endif
  857. #endif
  858. #endif
  859. LEVS: do level = 1, lmr
  860. rj(:,:,:) = rj_new (:,:,level,:)
  861. reff(:,:) = r_cloud(:,:,level)
  862. #ifdef with_budgets
  863. nzone_v=nzon_vg(level)
  864. #endif
  865. ! get/calculate all the fields needed in chemistry
  866. call GET_EXTRA( region, level, ye, i1, j1)
  867. ! calculate the rinc: relative radius growth of aerosols due to water
  868. ! Eqsam wants to calculate aerosol radii
  869. ! irinc is used by chem_rates in calchet2
  870. ! calchet2 is used by no one
  871. ! So, this part is not so important
  872. ! -----------------------------------
  873. ! To get this code back, take a stone-age copy of chemistry.F90
  874. ! But, to prevent even more errors.
  875. ! -----------------------------------
  876. ye(:,:,irinc) = 1.0
  877. call CALRATES(region, level, i1, j1, rj, rr, reff, ye, dtime, &
  878. sad_cld_out(:,:,level), sad_ice_out(:,:,level), sad_aer_out(:,:,level), status) ! also returns rh in ye
  879. IF_ERROR_RETURN(status=1)
  880. ! CALCULATE NOX EMISSIONS
  881. ! ---------------------------
  882. do j=j1,j2
  883. do i=i1,i2
  884. ! nox emis in this cell; init to zero:
  885. x = 0.0 ! kg(N)/month
  886. #ifndef without_emission
  887. ! add total 3d emissions if any
  888. if(associated(nox_emis_3d(region)%d3)) then
  889. x = x + nox_emis_3d(region)%d3(i,j,level)
  890. end if
  891. if(associated(nox_emis_3d_bb_app(region)%d3)) then
  892. x = x + nox_emis_3d_bb_app(region)%d3(i,j,level)
  893. end if
  894. #ifndef without_convection
  895. ! add lightning emissions:
  896. x = x + eminox_lightning(region)%d3(i,j,level)
  897. #endif
  898. #endif /* EMISS */
  899. ! emission budget (since nox emissions are added in chemistry)
  900. #ifdef with_budgets
  901. #ifndef without_emission
  902. budemi_dat(region)%emi(i,j,nzone_v,inox) = &
  903. budemi_dat(region)%emi(i,j,nzone_v,inox) + x/xmn*month2dt*1e3 ! g
  904. if (inox == 1) sum_emission(region) = sum_emission(region) + x*month2dt ! kg N
  905. #endif
  906. #endif
  907. ! put emissions in the units #/s/cm3 used in chemistry
  908. ye(i,j,ieno) = x/ye(i,j,iairm)*ye(i,j,iairn)* &
  909. (xmair/xmn)/sec_month !kg N/month ----> #(NO)/cm3/s
  910. end do
  911. end do
  912. ! INITIAL CONCENTRATIONS
  913. ! ---------------------------
  914. do n=1,ntracet
  915. do j=j1,j2
  916. do i=i1,i2
  917. y(i,j,n) = rm(i,j,level,n)/ye(i,j,iairm)*ye(i,j,iairn)* fscale(n) !kg ----> #/cm3
  918. end do
  919. end do
  920. end do
  921. do n=ntracet+1,ntrace
  922. do j=j1,j2
  923. do i=i1,i2
  924. ! remember nontransported tracers are in rmc
  925. y(i,j,n) =rmc(i,j,level,n)/ye(i,j,iairm)*ye(i,j,iairn)* fscale(n) !kg ----> #/cm3
  926. end do
  927. end do
  928. end do
  929. ! FILL EXTRA SPECIES : (from ntrace+1 to maxtrace)
  930. ! ---------------------------
  931. do j=j1,j2
  932. do i=i1,i2
  933. ! these are in #/cm3 and used in budget....should be in y....
  934. y(i,j,iair) = ye(i,j,iairn)
  935. y(i,j,ih2o) = ye(i,j,ih2on)
  936. ! introduced to calculate correct budget for JO2
  937. y(i,j,io2) = 1.
  938. ! precalculate as first order N2O5 loss.
  939. rr(i,j,kn2o5aq) = 0.
  940. end do
  941. end do
  942. ! BACKUP INIT CONCENTRATIONS
  943. ! ---------------------------
  944. y0 = y
  945. do klm=1,ntrace
  946. yhelp(:,:,klm) = y(:,:,klm)*ye(:,:,iairm)*1000./xmair/y(:,:,iair)
  947. end do
  948. ! EBI
  949. ! ---------------------------
  950. CALL EBI( region, level, i1, j1, rj, rr, y, ye, status)
  951. IF_ERROR_RETURN(status=1)
  952. ! EBI scheme budgets
  953. #ifdef with_budgets
  954. do j=j1,j2
  955. do i=i1,i2
  956. nzone=budg_dat(region)%nzong(i,j) ! global budget zone
  957. budchem(nzone,nzone_v,1:ntrace) = budchem(nzone,nzone_v,1:ntrace) + &
  958. y(i,j,1:ntrace)*ye(i,j,iairm)*1000./xmair/y(i,j,iair)-yhelp(i,j,:)
  959. end do
  960. end do
  961. #endif
  962. !--- Begin of M7: ------------------------------------------------------
  963. #ifdef with_m7
  964. ! M7
  965. iloop = 0
  966. do j=j1,j2
  967. do i=i1,i2
  968. #ifdef with_budgets
  969. ! For the M7 budgets, we first subtract the old concentrations.
  970. nzone=budg_dat(region)%nzong(i,j) ! global budget zone
  971. budm7(nzone,nzone_v,:)=budm7(nzone,nzone_v,:)-y(i,j,1:ntracet)*ye(i,j,iairm)*1000./xmair/y(i,j,iair)
  972. #endif
  973. iloop = iloop + 1
  974. ! meteo parameters
  975. presm7 (iloop,1) = ye(i,j,i_pres) ! Pa
  976. rhm7 (iloop,1) = rh(region)%d3(i,j,level) ! fraction, in cloud free part!
  977. tempm7 (iloop,1) = ye(i,j,i_temp) ! K
  978. dryairm7(iloop,1) = presm7(iloop,1)/(Rgas_air*tempm7(iloop,1)) ! density of dry air
  979. ! H2SO4 gas concentrations molecule/cm3
  980. h2so4m7(iloop,1) = y(i,j,iso4)/convsu
  981. ! molecule/cm3 ----> molecules/cm3
  982. ! sulphate mass in the 4 soluble modes molecule/cm3
  983. aemassm7(iloop,1,1) = y(i,j,iso4nus)/convsu
  984. aemassm7(iloop,1,2) = y(i,j,iso4ais)/convsu
  985. aemassm7(iloop,1,3) = y(i,j,iso4acs)/convsu
  986. aemassm7(iloop,1,4) = y(i,j,iso4cos)/convsu
  987. ! molecule/cm3 ----> molecules/cm3
  988. ! BC mass in the 3 soluble modes and 1 insoluble
  989. aemassm7(iloop,1,5) = y(i,j,ibcais)/convbc
  990. aemassm7(iloop,1,6) = y(i,j,ibcacs)/convbc
  991. aemassm7(iloop,1,7) = y(i,j,ibccos)/convbc
  992. aemassm7(iloop,1,8) = y(i,j,ibcaii)/convbc
  993. ! molecule/cm3 -----> ug/m3
  994. ! was: POM (tm5) OC (m7) mass in the 3 soluble modes and 1 insoluble
  995. ! POM mass in the 3 soluble modes and 1 insoluble
  996. aemassm7(iloop,1,9) = y(i,j,ipomais)/convoc
  997. aemassm7(iloop,1,10) = y(i,j,ipomacs)/convoc
  998. aemassm7(iloop,1,11) = y(i,j,ipomcos)/convoc
  999. aemassm7(iloop,1,12) = y(i,j,ipomaii)/convoc
  1000. ! molecule/cm3 -----> ug/m3
  1001. ! SS mass in the 2 soluble modes
  1002. aemassm7(iloop,1,13) = y(i,j,issacs)/convss
  1003. aemassm7(iloop,1,14) = y(i,j,isscos)/convss
  1004. ! molecule/cm3 -----> ug/m3
  1005. ! DUST mass in the 2 soluble modes and 2 insoluble
  1006. aemassm7(iloop,1,15) = y(i,j,iduacs)/convdu
  1007. aemassm7(iloop,1,16) = y(i,j,iducos)/convdu
  1008. aemassm7(iloop,1,17) = y(i,j,iduaci)/convdu
  1009. aemassm7(iloop,1,18) = y(i,j,iducoi)/convdu
  1010. ! molecule/cm3 -----> ug/m3
  1011. ! number concentrations of the 7 modes
  1012. aenumm7(iloop,1,1) = y(i,j,inus_n)/convnumb
  1013. aenumm7(iloop,1,2) = y(i,j,iais_n)/convnumb
  1014. aenumm7(iloop,1,3) = y(i,j,iacs_n)/convnumb
  1015. aenumm7(iloop,1,4) = y(i,j,icos_n)/convnumb
  1016. aenumm7(iloop,1,5) = y(i,j,iaii_n)/convnumb
  1017. aenumm7(iloop,1,6) = y(i,j,iaci_n)/convnumb
  1018. aenumm7(iloop,1,7) = y(i,j,icoi_n)/convnumb
  1019. !
  1020. ! molecule/cm3 -----> particle/cm3:
  1021. ! 1 # air
  1022. !rm in total aerosol number (#aer) ----> #aer * ------ * ------ is y
  1023. ! kg(air) cm-3
  1024. !#aer # air 1
  1025. !---- * ------- ----> 1 kg(air) = 10^3 g air = 10^3 * ----- * Avog
  1026. !cm-3 kg(air) xmair
  1027. !
  1028. end do
  1029. end do
  1030. ! The M7 processes will be calculated when budgets are used. The extra
  1031. ! argument will appear when the compiler flag with_budgets is set.
  1032. #ifdef with_budgets
  1033. call M7(iloop, imax, 1, & ! TM5 indices
  1034. presm7, rhm7, tempm7, & ! " thermodynamics
  1035. h2so4m7, aemassm7, aenumm7, & ! M7 tracers
  1036. aedensm7, aewatm7, aeradm7, aeradrm7, dtime, & ! M7 aerosol propertis
  1037. processm7 ) ! The extra argument, in which the rates of each process is stored in M7 units.
  1038. #else
  1039. call M7(iloop, imax, 1, & ! TM5 indices
  1040. presm7, rhm7, tempm7, & ! " thermodynamics
  1041. h2so4m7, aemassm7, aenumm7, & ! M7 tracers
  1042. aedensm7, aewatm7, aeradm7, aeradrm7, dtime) ! M7 aerosol propertis
  1043. #endif
  1044. iloop = 0
  1045. do j=j1,j2
  1046. do i=i1,i2
  1047. iloop = iloop + 1
  1048. ! H2SO4 gas concentrations in molecule/cm3
  1049. y(i,j,iso4) = h2so4m7(iloop,1)*convsu
  1050. ! molecule/cm3 ----> molecule/cm3
  1051. ! sulphate mass in the 4 soluble modes
  1052. y(i,j,iso4nus) = aemassm7(iloop,1,1)*convsu
  1053. y(i,j,iso4ais) = aemassm7(iloop,1,2)*convsu
  1054. y(i,j,iso4acs) = aemassm7(iloop,1,3)*convsu
  1055. y(i,j,iso4cos) = aemassm7(iloop,1,4)*convsu
  1056. ! molecule/cm3 ----> molecule/cm3
  1057. ! BC mass in the 3 soluble modes and 1 insoluble
  1058. y(i,j,ibcais) = aemassm7(iloop,1,5)*convbc
  1059. y(i,j,ibcacs) = aemassm7(iloop,1,6)*convbc
  1060. y(i,j,ibccos) = aemassm7(iloop,1,7)*convbc
  1061. y(i,j,ibcaii) = aemassm7(iloop,1,8)*convbc
  1062. ! ug/m3 ----> molecule/cm3
  1063. ! was: POM (tm5) OC (m7) mass in the 3 soluble modes and 1 insoluble
  1064. ! POM mass in the 3 soluble modes and 1 insoluble
  1065. y(i,j,ipomais) = aemassm7(iloop,1,9)*convoc
  1066. y(i,j,ipomacs) = aemassm7(iloop,1,10)*convoc
  1067. y(i,j,ipomcos) = aemassm7(iloop,1,11)*convoc
  1068. y(i,j,ipomaii) = aemassm7(iloop,1,12)*convoc
  1069. ! ug/m3 ----> molecule/cm3
  1070. ! SS mass in the 2 soluble modes
  1071. y(i,j,issacs) = aemassm7(iloop,1,13)*convss
  1072. y(i,j,isscos) = aemassm7(iloop,1,14)*convss
  1073. ! ug/m3 ----> molecule/cm3
  1074. ! DUST mass in the 2 soluble modes and 2 insoluble
  1075. y(i,j,iduacs) = aemassm7(iloop,1,15)*convdu
  1076. y(i,j,iducos) = aemassm7(iloop,1,16)*convdu
  1077. y(i,j,iduaci) = aemassm7(iloop,1,17)*convdu
  1078. y(i,j,iducoi) = aemassm7(iloop,1,18)*convdu
  1079. ! ug/m3 ----> molecule/cm3
  1080. ! number concentrations of the 7 modes
  1081. y(i,j,inus_n) = aenumm7(iloop,1,1)*convnumb
  1082. y(i,j,iais_n) = aenumm7(iloop,1,2)*convnumb
  1083. y(i,j,iacs_n) = aenumm7(iloop,1,3)*convnumb
  1084. y(i,j,icos_n) = aenumm7(iloop,1,4)*convnumb
  1085. y(i,j,iaii_n) = aenumm7(iloop,1,5)*convnumb
  1086. y(i,j,iaci_n) = aenumm7(iloop,1,6)*convnumb
  1087. y(i,j,icoi_n) = aenumm7(iloop,1,7)*convnumb
  1088. !number of particles/cm3 ----> molecule/cm3 (see comment above)
  1089. #ifdef with_budgets
  1090. ! For the M7 budgets, we now add the new concentrations.
  1091. nzone=budg_dat(region)%nzong(i,j) ! global budget zone
  1092. budm7(nzone,nzone_v,:)=budm7(nzone,nzone_v,:)+y(i,j,1:ntracet)*ye(i,j,iairm)*1000./xmair/y(i,j,iair)
  1093. budm7proc(nzone,nzone_v,:)=budm7proc(nzone,nzone_v,:)+processm7(iloop,1,:)*processm7totm5*ye(i,j,iairm)*&
  1094. 1000./xmair/y(i,j,iair) ! processm7totm5 is a 66-element array with unit conversion factors.
  1095. #endif
  1096. ! output m7
  1097. ! kgH2O/m3 ---> kg water per gridbox
  1098. do imode=1,nsol
  1099. h2o_mode(region,imode)%d3(i,j,level) = aewatm7(iloop,1,imode) *dxyp(j)*ye(i,j,idz)
  1100. rwd_mode (region,imode)%d3(i,j,level) = aeradrm7(iloop,1,imode)*1e-2 ! from cm to meter
  1101. end Do
  1102. do imode=1,nmod
  1103. dens_mode(region,imode)%d3(i,j,level) = aedensm7(iloop,1,imode)*1e3 ! from g/cm^3 --> kg/m^3
  1104. rw_mode (region,imode)%d3(i,j,level) = aeradm7(iloop,1,imode)*1e-2 ! from cm to meter
  1105. End Do
  1106. end do
  1107. end do
  1108. #endif /* M7 */
  1109. ! ====================== EQSAM ! Using HNO3 / NO3_A, NH4 / NH2 and SO4.
  1110. yi = 0.0
  1111. yo = 0.0
  1112. iloop = 0
  1113. do j=j1,j2
  1114. do i=i1,i2
  1115. iloop = iloop + 1
  1116. yi(iloop,1)=ye(i,j,i_temp) ! K
  1117. #ifndef without_sedimentation
  1118. #ifdef with_m7
  1119. s = rh(region)%d3(i,j,level) ! in cloud free part!
  1120. #else
  1121. s = 0.0
  1122. #endif
  1123. #else
  1124. s = 0.0
  1125. #endif
  1126. yi(iloop,2)=max(0.001,min(0.95,s))
  1127. yi(iloop,11)=ye(i,j,i_pres)/100. ! Pa -> hPa
  1128. ! yi(iloop,6)= c(nv2,ina)/Avog*1.e12
  1129. yi(iloop,6)=0.
  1130. #ifdef with_m7
  1131. yi(iloop,4)=(y(i,j,iso4)+y(i,j,iso4nus)+y(i,j,iso4ais)+y(i,j,iso4acs)+y(i,j,iso4cos))/Avog*1.e12 ! molec/cm3 -> umol/m3
  1132. #else
  1133. yi(iloop,4)=(y(i,j,iso4))/Avog*1.e12 ! molec/cm3 -> umol/m3
  1134. #endif
  1135. yi(iloop,3)=(y(i,j,inh3)+y(i,j,inh4))/Avog*1.e12
  1136. yi(iloop,5)=(y(i,j,ihno3)+y(i,j,ino3_a))/Avog*1.e12
  1137. !yi(iloop,7)=(c(nv2,ihcl)+c(nv2,icl))/Avog*1.e12
  1138. yi(iloop,7)=0.
  1139. !yi(iloop,8)=c(nv2,ik)/Avog*1.e12
  1140. yi(iloop,8)=0.
  1141. !yi(iloop,9)=c(nv2,ica)/Avog*1.e12
  1142. yi(iloop,9)=0.
  1143. !yi(iloop,10)=c(nv2,img)/Avog*1.e12
  1144. yi(iloop,10)=0.
  1145. end do
  1146. end do
  1147. eqsam_option = 1
  1148. call EQSAM_V03D( yi, yo, nca, nco, eqsam_option, iloop, imax, 0, (/0,0,0,0,0,0/))
  1149. iloop = 0
  1150. do j=j1,j2
  1151. do i=i1,i2
  1152. iloop = iloop + 1
  1153. #ifdef with_budgets
  1154. nzone=budg_dat(region)%nzong(i,j) ! global budget zone
  1155. budeqsam(nzone,nzone_v,1) = budeqsam(nzone,nzone_v,1) + &
  1156. (yo(iloop,19)*Avog*1.e-12-y(i,j,inh4)) *ye(i,j,iairm)*1000./xmair/y(i,j,iair) ! Ammonium
  1157. budeqsam(nzone,nzone_v,2) = budeqsam(nzone,nzone_v,2) + &
  1158. (yo(iloop,20)*Avog*1.e-12-y(i,j,ino3_a))*ye(i,j,iairm)*1000./xmair/y(i,j,iair) ! Nitrate
  1159. #endif
  1160. y(i,j,ihno3) = yo(iloop, 9)*Avog*1.e-12 ! umol/m3 -> molec/cm3
  1161. y(i,j,inh3) = yo(iloop,10)*Avog*1.e-12 ! umol/m3 -> molec/cm3
  1162. y(i,j,inh4) = yo(iloop,19)*Avog*1.e-12 ! umol/m3 -> molec/cm3
  1163. y(i,j,ino3_a) = yo(iloop,20)*Avog*1.e-12 ! umol/m3 -> molec/cm3
  1164. ! Sulfuric acid is unchanged:
  1165. ! y(i,j,iso4) = yo(iloop,21)*Avog*1.e-12
  1166. ! The NO3_A should also get some water. M7 takes the water for the
  1167. ! anoins: SO4-- and Cl- (Sea Salt). Cations are neglected.
  1168. ! Just the NO3- water is used apart from the M7 water.
  1169. ! Ignore the direct eqsam water
  1170. ! ug/m3 -> molec/cm3
  1171. ! y(i,j,ih2opart) = yo(iloop,12)*Avog*1.e-12/xmh2o
  1172. #ifdef with_m7
  1173. ! The water associated with nitrate aerosol is put into
  1174. ! the soluble accumulation mode.
  1175. h2o_mode(region,3)%d3(i,j,level) = h2o_mode(region,3)%d3(i,j,level) + yo(iloop,37)*dxyp(j)*ye(i,j,idz)*1.e-9
  1176. ! from ug/m^3 (according to eqsam), then take the M7 conversion (from kg/m^3) times 1.e-9.
  1177. ! This EQSAM water is added to the optics water at the call of optics.
  1178. #endif
  1179. end do
  1180. end do
  1181. ! END EQSAM
  1182. ! Check for negative concentrations.
  1183. do n=1,ntrace
  1184. do j=j1,j2
  1185. do i=i1,i2
  1186. if ( y(i,j,n) < 0. ) then
  1187. !print *,' chemistry: negatives appeared in chemie'
  1188. !write(6,*)i,j,level,idater
  1189. !write(6,907)(y0(i,j,ispec),ispec=1,ntrace)
  1190. !write(6,907)(y(i,j,ispec),ispec=1,ntrace)
  1191. if ( n > ntracet ) then
  1192. do ispec=ntracet+1,ntrace
  1193. y(i,j,ispec)=max(0.,y(i,j,ispec))
  1194. end do
  1195. else
  1196. write (gol,'(a,a8,a,4i4,e12.4)') &
  1197. 'chemistry: negatives for species:',names(n), ' at ', i,j,level,region, &
  1198. y(i,j,n)/y(i,j,iair); call goPr
  1199. y(i,j,n)=max(0.,y(i,j,n))
  1200. end if
  1201. end if
  1202. end do !i
  1203. end do !j
  1204. end do !n
  1205. ! Write the tracers back to the mass_dat (rm)
  1206. do n=1,ntrace
  1207. #ifdef with_cariolle
  1208. if ( (n==io3) .and. ( (level.ge.l_cariolle(region)) .or. with_trop_force ) ) then
  1209. ! O3 is changed by Cariolle chemistry
  1210. else
  1211. #endif
  1212. do j=j1,j2
  1213. do i=i1,i2
  1214. if ( n <= ntracet ) then
  1215. rm(i,j,level,n)=y(i,j,n)/y(i,j,iair)*ye(i,j,iairm)/fscale(n)
  1216. else
  1217. rmc(i,j,level,n)=y(i,j,n)/y(i,j,iair)*ye(i,j,iairm)/fscale(n)
  1218. end if
  1219. #ifdef slopes
  1220. if ( n <= ntracet ) then
  1221. skf=0.
  1222. if ( y(i,j,n) > eps .and. y0(i,j,n) > eps ) skf=y(i,j,n)/y0(i,j,n)
  1223. rxm(i,j,level,n)=rxm(i,j,level,n)*skf
  1224. rym(i,j,level,n)=rym(i,j,level,n)*skf
  1225. rzm(i,j,level,n)=rzm(i,j,level,n)*skf
  1226. #ifdef secmom
  1227. rxxm(i,j,level,n)=rxxm(i,j,level,n)*skf
  1228. rxym(i,j,level,n)=rxym(i,j,level,n)*skf
  1229. rxzm(i,j,level,n)=rxzm(i,j,level,n)*skf
  1230. ryym(i,j,level,n)=ryym(i,j,level,n)*skf
  1231. ryzm(i,j,level,n)=ryzm(i,j,level,n)*skf
  1232. rzzm(i,j,level,n)=rzzm(i,j,level,n)*skf
  1233. #endif
  1234. endif
  1235. #endif
  1236. end do
  1237. end do !j,i
  1238. #ifdef with_cariolle
  1239. endif
  1240. #endif
  1241. end do !n
  1242. ! For the optics calculations,
  1243. ! it is assumed that nitrate aerosol is formed
  1244. ! by condensation onto existing particles
  1245. ! in the soluble accumulation mode (Adams et al., JGR, 2001).
  1246. ! Therefore, the presence of nitrate does not increase
  1247. ! the number of particles, nor does it have an impact
  1248. ! on the processes described by M7.
  1249. ! Above, the water associated with nitrate aerosol
  1250. ! is added to the total aerosol water (h2o_mode) in the accumulation mode.
  1251. ! However, this only affects the calculation of the refractive index,
  1252. ! which also accounts for the nitrate mass itself.
  1253. ! In order to properly account for the additional ammonium nitrate
  1254. ! and the associated water in the optics routine,
  1255. ! the corresponding dry and wet particle radii have to be increased as well;
  1256. ! the aerosol density (dens_mode) can be left unchanged,
  1257. ! because it is not used in the optics routine.
  1258. ! We use the same refractive index for ammonium nitrate as for sulfate.
  1259. ! This is a reasonable approximation, since,
  1260. ! according to Tang (JGR, 1997), for sulfate and nitrate aerosols
  1261. ! the effect of chemical composition on light scattering
  1262. ! is outweighted by the size effect of the particles.
  1263. ! Lowenthal et al. (Atmos. Environ., 2000)
  1264. ! give a refractive index of 1.44 for sulfuric acid
  1265. ! and 1.55 for ammonium nitrate.
  1266. ! If desired, the refractive index of ammonium nitrate
  1267. ! could be estimated at different wavelengths
  1268. ! by scaling the OPAC data for sulfate,
  1269. ! based on these values.
  1270. ! In M7 and in the optics calculations,
  1271. ! sulfate aerosols are assumed to be pure sulfuric acid,
  1272. ! and we do not try to account for the presence of ammonium (bi)sulfate.
  1273. ! The reason is that the presence of ammonium (bi)sulfate
  1274. ! has competing effects on scattering,
  1275. ! which cannot be easily accounted for in a model based on M7.
  1276. ! Sulfuric acid particles are extremely hygroscopic
  1277. ! and will draw significant water mass into the aerosol phase
  1278. ! at any relative humidity (RH).
  1279. ! If these particles are partially or completely neutralized
  1280. ! by drawing ammonia from the gas phase,
  1281. ! there will be an increase in particle mass due to the added ammonium
  1282. ! but a decrease in particle hygroscopicity at low to moderate RH,
  1283. ! and thus a decrease in particulate water mass.
  1284. ! On the other hand, ammonium bisulfate and ammonium sulfate both
  1285. ! have a higher refractive index than sulfuric acid (see e.g. Boucher and Anderson, 1995).
  1286. ! The net result of these competing factors is that
  1287. ! one mole of sulfuric acid scatters about 25% more sunlight
  1288. ! than one mole of ammonium bisulfate at 80% relative humidity.
  1289. ! Ammonium sulfate is intermediate between the two.
  1290. ! For more information see Boucher and Anderson (1995) and Boucher et al. (JGR, 1998).
  1291. ! An excellent discussion of the optical properties of ammonium (bi)sulfate
  1292. ! versus sulfuric acid is also given by Adams et al. (JGR, 2001).
  1293. !
  1294. ! In remote regions, especially outside the tropics,
  1295. ! the contribution of methane sulfonate (MSA-) aerosol
  1296. ! to the total particulate sulfure burden
  1297. ! cannot be neglected.
  1298. ! Like nitrate, MSA- aerosols are mainly formed by
  1299. ! condensation onto exisiting particles,
  1300. ! in the soluble accumulation and coarse modes
  1301. ! (Saltzmann et al., JGR, 1983; Pzenny et al., J. Atmos. Chem., 1992).
  1302. ! For simplicity, we assume in the model
  1303. ! that MSA- is formed only in the accumulation mode.
  1304. ! Moreover, it seems reasonable to use the refractive index of
  1305. ! sulfuric acid (H2SO4) for MSA, as is done by Kinne et al. (2003).
  1306. ! The similarity between the refractive index for MSA and H2SO4
  1307. ! is also discussed by Myhre et al. (Applied Optics, 2004).
  1308. !
  1309. #ifdef with_m7
  1310. do j=j1,j2
  1311. do i=i1,i2
  1312. ! prevent division for zero for extremely low aerosol concentrations
  1313. ! calculate corresponding number concentration in #/cm3
  1314. ! and test if this is larger than 1.e-10
  1315. ! the same criterion is applied in m7_equil
  1316. number_conc = rm(i,j,level,iacs_n) / ( 1.e6 * dxyp(j) * ye(i,j,idz) )
  1317. if ( number_conc > 1.e-10 ) then
  1318. dryvol_m7=((rwd_mode(region,3)%d3(i,j,level)*cmr2ram(3))**3.0)*pi/0.75 ! dry particle volume [m3]
  1319. ! in the accumulation mode from M7
  1320. vol_nh4no3=rm(i,j,level,ino3_a)*nh4no3_factor/ &
  1321. (rm(i,j,level,iacs_n)*nh4no3_density) ! ammonium-nitrate aerosol volume per particle [m3]
  1322. vol_msa=rm(i,j,level,imsa)/(rm(i,j,level,iacs_n)*msa_density) ! MSA- aerosol volume per particle [m3]
  1323. vol_h2o=h2o_mode(region,3)%d3(i,j,level)/(rm(i,j,level,iacs_n)*rol) ! total aerosol water per particle [m3]
  1324. rw_mode(region,3)%d3(i,j,level) = ((dryvol_m7+vol_nh4no3+vol_msa+vol_h2o)*0.75/pi)**(1./3.)*ram2cmr(3)
  1325. rwd_mode(region,3)%d3(i,j,level) = ((dryvol_m7+vol_nh4no3+vol_msa)*0.75/pi)**(1./3.)*ram2cmr(3)
  1326. else
  1327. ! don't change rwd_mode and set rw_mode equal to rwd_mode
  1328. rw_mode(region,3)%d3(i,j,level) = rwd_mode(region,3)%d3(i,j,level)
  1329. endif
  1330. enddo
  1331. enddo
  1332. #endif
  1333. end do LEVS ! loop over vertical levels...
  1334. ! SAD
  1335. phot_dat(region)%sad_cld=sad_cld_out
  1336. phot_dat(region)%sad_ice=sad_ice_out
  1337. phot_dat(region)%sad_aer=sad_aer_out
  1338. ! perform averaging...
  1339. phot_dat(region)%nsad_av = phot_dat(region)%nsad_av + float(ndyn)/float(ndyn_max)
  1340. phot_dat(region)%sad_cld_av = phot_dat(region)%sad_cld_av + (float(ndyn)/float(ndyn_max))*phot_dat(region)%sad_cld
  1341. phot_dat(region)%sad_ice_av = phot_dat(region)%sad_ice_av + (float(ndyn)/float(ndyn_max))*phot_dat(region)%sad_ice
  1342. phot_dat(region)%sad_aer_av = phot_dat(region)%sad_aer_av + (float(ndyn)/float(ndyn_max))*phot_dat(region)%sad_aer
  1343. ! cleanup
  1344. deallocate(tha)
  1345. deallocate(mu)
  1346. deallocate(sza)
  1347. deallocate(reff)
  1348. deallocate(fact)
  1349. deallocate(rj)
  1350. deallocate(rj_new)
  1351. deallocate(rr)
  1352. deallocate(y)
  1353. deallocate(y0)
  1354. deallocate(ye, yhelp)
  1355. ! eqsam
  1356. deallocate(yo)
  1357. deallocate(yi)
  1358. ! sad
  1359. deallocate(sad_cld_out,sad_ice_out,sad_aer_out)
  1360. #ifdef with_m7
  1361. deallocate(presm7)
  1362. deallocate(rhm7)
  1363. deallocate(tempm7)
  1364. deallocate(dryairm7)
  1365. deallocate(h2so4m7)
  1366. deallocate(aemassm7)
  1367. deallocate(aenumm7)
  1368. deallocate(aedensm7)
  1369. deallocate(aewatm7)
  1370. deallocate(aeradm7)
  1371. deallocate(aeradrm7)
  1372. #ifdef with_budgets
  1373. deallocate(processm7)
  1374. #endif
  1375. nullify(dxyp)
  1376. #endif
  1377. nullify(m)
  1378. nullify(rm)
  1379. #ifdef slopes
  1380. nullify(rxm)
  1381. nullify(rym)
  1382. nullify(rzm)
  1383. #ifdef secmom
  1384. nullify(rxxm)
  1385. nullify(rxym)
  1386. nullify(rxzm)
  1387. nullify(ryym)
  1388. nullify(ryzm)
  1389. nullify(rzzm)
  1390. #endif
  1391. #endif
  1392. nullify(r_cloud)
  1393. if ( okdebug ) write (*,*) 'end of chemistry'
  1394. ! ok
  1395. status = 0
  1396. END SUBROUTINE CHEMIE
  1397. !EOC
  1398. !--------------------------------------------------------------------------
  1399. ! TM5 !
  1400. !--------------------------------------------------------------------------
  1401. !BOP
  1402. !
  1403. ! !IROUTINE: GET_EXTRA
  1404. !
  1405. ! !DESCRIPTION:
  1406. ! calculate / get 2D fields needed in the chemistry routines...
  1407. ! some fields (like pH) are calculated later on...
  1408. !\\
  1409. !\\
  1410. ! !INTERFACE:
  1411. !
  1412. SUBROUTINE GET_EXTRA( region, level, ye, is, js)
  1413. !
  1414. ! !USES:
  1415. !
  1416. use Binas, only : Avog, grav
  1417. use dims, only : im, jm, lm
  1418. use Dims, only : CheckShape
  1419. use global_data, only : region_dat, mass_dat
  1420. use meteodata, only : phlb_dat, m_dat, temper_dat, humid_dat, gph_dat, cc_dat, iwc_dat, lwc_dat
  1421. use chem_param, only : n_extra, i_pres, i_temp, iairn, ih2on
  1422. use chem_param, only : xmair, xmh2o, iairm, ilwc, iiwc, icc, iph, idz,iciwc,iclwc
  1423. !
  1424. ! !INPUT PARAMETERS:
  1425. !
  1426. integer, intent(in) :: region ! region #
  1427. integer, intent(in) :: level, is, js ! level and start indices
  1428. !
  1429. ! !OUTPUT PARAMETERS:
  1430. !
  1431. real, intent(out) :: ye(is:,js:,:)
  1432. !
  1433. ! !REVISION HISTORY:
  1434. ! 22 Mar 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  1435. !
  1436. ! !REMARKS:
  1437. !
  1438. !EOP
  1439. !------------------------------------------------------------------------
  1440. !BOC
  1441. real,dimension(:,:,:),pointer :: phlb,m,gph,t,q,lwc,iwc,cc
  1442. integer :: i,j,l
  1443. real :: px,x1,x2,xice,xliq,aird
  1444. integer :: imr, jmr, lmr, i1, i2, j1, j2, status
  1445. ! --- begin --------------------------------
  1446. call Get_DistGrid( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
  1447. ! check arguments ...
  1448. call CheckShape( (/i2-i1+1, j2-j1+1, n_extra/), shape(ye ), status )
  1449. lmr = lm(region)
  1450. phlb => phlb_dat(region)%data
  1451. m => m_dat(region)%data
  1452. t => temper_dat(region)%data
  1453. q => humid_dat(region)%data
  1454. gph => gph_dat(region)%data ! (:,:,1:lm(region)+1)
  1455. lwc => lwc_dat(region)%data
  1456. iwc => iwc_dat(region)%data
  1457. cc => cc_dat(region)%data
  1458. do j=j1,j2
  1459. do i=i1,i2
  1460. px = 0.5*(phlb(i,j,level)+phlb(i,j,level+1))
  1461. ye(i,j,i_pres) = px
  1462. ye(i,j,i_temp) = t(i,j,level)
  1463. ye(i,j,iairn ) = 7.24e16*px/t(i,j,level)
  1464. ye(i,j,ih2on ) = q(i,j,level)*ye(i,j,iairn)*xmair/xmh2o
  1465. ye(i,j,iairm ) = m(i,j,level)
  1466. ye(i,j,iclwc ) = lwc(i,j,level)
  1467. ye(i,j,iciwc ) = iwc(i,j,level)
  1468. ! x1: kg water to m3 water (m3 water/ kg air)
  1469. x1=lwc(i,j,level)*1.e-3
  1470. aird = ye(i,j,iairn)
  1471. x2=xmair*1e3*aird/Avog ! kg/m3 (air)
  1472. xliq = x1/x2 ! dimensionless number (m^3/m^3)
  1473. ! avoid negatives and artificial values(1e-10 is about 0.0001 g/m3)
  1474. if ( xliq < 1e-10 ) xliq=0.
  1475. ye(i,j,ilwc) = xliq
  1476. x1=iwc(i,j,level)*1.e-3 ! kg ice to m3 ice
  1477. xice=x1/x2
  1478. ! avoid negatives and artificial values)
  1479. if ( xice < 1e-10 ) xice=0.
  1480. ye(i,j,iiwc) = xice
  1481. ye(i,j,icc) = cc(i,j,level)
  1482. ye(i,j,iph) = 0.0 ! only set in wetS when cloudy!!!
  1483. ye(i,j,idz) = gph(i,j,level+1)-gph(i,j,level) !dz
  1484. end do
  1485. end do
  1486. nullify(phlb)
  1487. nullify(m)
  1488. nullify(gph)
  1489. nullify(t)
  1490. nullify(q)
  1491. nullify(lwc)
  1492. nullify(iwc)
  1493. nullify(cc)
  1494. END SUBROUTINE GET_EXTRA
  1495. !EOC
  1496. END MODULE CHEMISTRY