emission_co2.F90 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. !
  2. #define TRACEBACK write (gol,'("in ",a," (",a,", line",i5,")")') rname, __FILE__, __LINE__; call goErr
  3. #define IF_NOTOK_RETURN(action) if (status/=0) then; TRACEBACK; action; return; end if
  4. #define IF_ERROR_RETURN(action) if (status> 0) then; TRACEBACK; action; return; end if
  5. !
  6. #include "tm5.inc"
  7. !
  8. !-----------------------------------------------------------------------------
  9. ! TM5 !
  10. !-----------------------------------------------------------------------------
  11. !BOP
  12. !
  13. ! !MODULE: EMISSION_CO2
  14. !
  15. ! !DESCRIPTION: Hold data and methods for CO2 emissions.
  16. !\\
  17. !\\
  18. ! !INTERFACE:
  19. !
  20. MODULE EMISSION_CO2
  21. !
  22. ! !USES:
  23. !
  24. use GO, only : gol, goErr, goPr
  25. use dims, only : nregions, idate
  26. use global_types, only : emis_data, d3_data
  27. use emission_read, only : used_providers, has_emis
  28. use tm5_distgrid, only : dgrid, get_distgrid, scatter
  29. use partools, only : isRoot, par_broadcast
  30. implicit none
  31. private
  32. !
  33. ! !PUBLIC MEMBER FUNCTIONS:
  34. !
  35. public :: Emission_CO2_Init ! allocate dataset
  36. public :: Emission_CO2_Done ! deallocate dataset
  37. public :: Emission_CO2_Declare ! read monthly input
  38. public :: Emission_CO2_Apply ! distribute & add emissions to tracer array
  39. !
  40. ! !PRIVATE DATA MEMBERS:
  41. !
  42. character(len=*), parameter :: mname = 'emission_co2'
  43. type( emis_data ), dimension(:,:), allocatable :: co2_emis_2d
  44. type( d3_data ), dimension(:,:), allocatable :: co2_emis_3d
  45. integer :: co2_2dsec, co2_3dsec
  46. !
  47. ! !REVISION HISTORY:
  48. ! 1 Oct 2010 - Achim Strunk - revamped for AR5
  49. ! 26 Jun 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  50. ! 14 May 2014 - T. van Noije - created CO2 version from CO version
  51. ! to be done: convert CMIP5 CO2 input files
  52. ! for emissions from fossil fuel use and land use
  53. ! into the same format as for the other trace species
  54. !
  55. ! !REMARKS:
  56. !
  57. !EOP
  58. !------------------------------------------------------------------------
  59. CONTAINS
  60. !--------------------------------------------------------------------------
  61. ! TM5 !
  62. !--------------------------------------------------------------------------
  63. !BOP
  64. !
  65. ! !IROUTINE: EMISSION_CO2_INIT
  66. !
  67. ! !DESCRIPTION: Allocate memory to handle the emissions.
  68. !\\
  69. !\\
  70. ! !INTERFACE:
  71. !
  72. SUBROUTINE EMISSION_CO2_INIT( status )
  73. !
  74. ! !USES:
  75. !
  76. use dims, only : lm
  77. use emission_read, only : providers_def, numb_providers
  78. !
  79. ! !OUTPUT PARAMETERS:
  80. !
  81. integer, intent(out) :: status
  82. !
  83. ! !REVISION HISTORY:
  84. ! 1 Oct 2010 - Achim Strunk - v0
  85. ! 26 Jun 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  86. !
  87. !EOP
  88. !------------------------------------------------------------------------
  89. !BOC
  90. character(len=*), parameter :: rname = mname//'/Emission_CO2_Init'
  91. integer :: region
  92. integer :: imr, jmr, lmr, lsec, lprov, i1, i2, j1, j2
  93. ! --- begin --------------------------------------
  94. status = 0
  95. if(.not. has_emis) return
  96. ! nb of sectors
  97. co2_2dsec = 0
  98. co2_3dsec = 0
  99. do lprov = 1, numb_providers
  100. if (count(used_providers.eq.providers_def(lprov)%name)/=0) then
  101. co2_2dsec = co2_2dsec + providers_def(lprov)%nsect2d
  102. co2_3dsec = co2_3dsec + providers_def(lprov)%nsect3d
  103. endif
  104. enddo
  105. allocate( co2_emis_2d( nregions, co2_2dsec ) )
  106. allocate( co2_emis_3d( nregions, co2_3dsec ) )
  107. ! allocate information arrays (2d and 3d)
  108. do region=1,nregions
  109. CALL GET_DISTGRID( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
  110. lmr = lm(region)
  111. do lsec=1,co2_2dsec
  112. allocate( co2_emis_2d(region,lsec)%surf(i1:i2,j1:j2) )
  113. end do
  114. do lsec=1,co2_3dsec
  115. allocate( co2_emis_3d(region,lsec)%d3(i1:i2,j1:j2,lmr) )
  116. end do
  117. enddo
  118. ! ok
  119. status = 0
  120. END SUBROUTINE EMISSION_CO2_INIT
  121. !EOC
  122. !--------------------------------------------------------------------------
  123. ! TM5 !
  124. !--------------------------------------------------------------------------
  125. !BOP
  126. !
  127. ! !IROUTINE: EMISSION_CO2_DONE
  128. !
  129. ! !DESCRIPTION: Free memory after handling of the emissions.
  130. !\\
  131. !\\
  132. ! !INTERFACE:
  133. !
  134. SUBROUTINE EMISSION_CO2_DONE( status )
  135. !
  136. ! !OUTPUT PARAMETERS:
  137. !
  138. integer, intent(out) :: status
  139. !
  140. ! !REVISION HISTORY:
  141. ! 1 Oct 2010 - Achim Strunk - v0
  142. !
  143. !EOP
  144. !------------------------------------------------------------------------
  145. !BOC
  146. character(len=*), parameter :: rname = mname//'/Emission_CO2_Done'
  147. integer :: region, lsec
  148. ! --- begin --------------------------------------
  149. status = 0
  150. if(.not. has_emis) return
  151. do region = 1, nregions
  152. do lsec=1,co2_2dsec
  153. deallocate( co2_emis_2d(region,lsec)%surf )
  154. end do
  155. do lsec=1,co2_3dsec
  156. deallocate( co2_emis_3d(region,lsec)%d3 )
  157. end do
  158. end do
  159. deallocate( co2_emis_2d )
  160. deallocate( co2_emis_3d )
  161. ! ok
  162. status = 0
  163. END SUBROUTINE EMISSION_CO2_DONE
  164. !EOC
  165. !--------------------------------------------------------------------------
  166. ! TM5 !
  167. !--------------------------------------------------------------------------
  168. !BOP
  169. !
  170. ! !IROUTINE: EMISSION_CO2_DECLARE
  171. !
  172. ! !DESCRIPTION: Opens, reads and evaluates input files (per month).
  173. ! Provides emissions on 2d/3d-arrays which are then added
  174. ! to mixing ratios in routine *apply.
  175. !\\
  176. !\\
  177. ! !INTERFACE:
  178. !
  179. SUBROUTINE EMISSION_CO2_DECLARE( status )
  180. !
  181. ! !USES:
  182. !
  183. use toolbox, only : coarsen_emission
  184. use dims, only : im, jm, lm, idate, sec_month, nlon360, nlat180, iglbsfc
  185. use chem_param, only : xmco2
  186. use emission_data, only : msg_emis
  187. ! ---------------- AR5 - ETC. --------------------
  188. use emission_data, only : emis_input_year
  189. use emission_read, only : emission_ar5_ReadCO2
  190. use emission_read, only : sectors_def, numb_sectors
  191. use emission_read, only : ar5_dim_3ddata
  192. !
  193. ! !OUTPUT PARAMETERS:
  194. !
  195. integer, intent(out) :: status
  196. !
  197. ! !REVISION HISTORY:
  198. ! 1 Oct 2010 - Achim Strunk - adapted for AR5
  199. ! 26 Jun 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  200. !
  201. ! !REMARKS:
  202. !
  203. !EOP
  204. !------------------------------------------------------------------------
  205. !BOC
  206. character(len=*), parameter :: rname = mname//'/emission_co2_declare'
  207. integer :: region, hasData
  208. integer, parameter :: add_field=0
  209. integer, parameter :: amonth=2
  210. integer :: imr, jmr, lmr, lsec
  211. ! AR5
  212. real,dimension(:,:,:), allocatable :: field3d, field3d2
  213. type(d3_data) :: emis3d, work(nregions)
  214. type(emis_data) :: wrk2D(nregions)
  215. integer :: seccount2d, seccount3d
  216. ! --- begin -----------------------------------------
  217. status = 0
  218. if(.not. has_emis) return
  219. do region = 1, nregions
  220. do lsec=1,co2_2dsec
  221. co2_emis_2d(region,lsec)%surf = 0.0
  222. end do
  223. do lsec=1,co2_3dsec
  224. co2_emis_3d(region,lsec)%d3 = 0.0
  225. end do
  226. end do
  227. ! global arrays for coarsening
  228. do region = 1, nregions
  229. if (isRoot)then
  230. allocate(work(region)%d3(im(region),jm(region),lm(region)))
  231. else
  232. allocate(work(region)%d3(1,1,1))
  233. end if
  234. enddo
  235. do region = 1, nregions
  236. wrk2D(region)%surf => work(region)%d3(:,:,1)
  237. end do
  238. ! --------------------------------
  239. ! do a loop over available sectors
  240. ! --------------------------------
  241. ! count 2d and 3d sectors
  242. seccount2d = 0
  243. seccount3d = 0
  244. ! always allocate here 3d data set (for 2d sectors it will be filled in first layer only)
  245. if (isRoot) then
  246. allocate( field3d( nlon360, nlat180, ar5_dim_3ddata ) ) ; field3d = 0.0
  247. else
  248. allocate( field3d( 1, 1, 1 ) )
  249. end if
  250. sec : do lsec = 1, numb_sectors
  251. if (count(used_providers.eq.sectors_def(lsec)%prov).eq.0) cycle
  252. field3d = 0.0
  253. if( sectors_def(lsec)%f3d ) then
  254. seccount3d = seccount3d + 1
  255. else
  256. seccount2d = seccount2d + 1
  257. end if
  258. if (isRoot) then ! READ
  259. select case( trim(sectors_def(lsec)%prov) )
  260. case( 'AR5' )
  261. call emission_ar5_ReadCO2( 'CO2', emis_input_year, idate(2), lsec, field3d, status )
  262. IF_NOTOK_RETURN(status=1;deallocate(field3d))
  263. case('DUMMY')
  264. case default
  265. write(gol,*) "Error in buidling list of providers USED_PROVIDERS"; call goErr
  266. status=1; TRACEBACK; return
  267. end select
  268. ! nothing found???
  269. if( sum(field3d) < 100.*TINY(1.0) ) then
  270. write(gol,'("EMISS-INFO - no CO2 emissions found for ",a," ",a," for month ",i2 )') &
  271. trim(sectors_def(lsec)%prov), trim(sectors_def(lsec)%name), idate(2) ; call goPr
  272. hasData=0
  273. else
  274. write(gol,'("EMISS-INFO - found CO2 emissions for ",a," ",a," for month ",i2 )') &
  275. trim(sectors_def(lsec)%prov), trim(sectors_def(lsec)%name), idate(2) ; call goPr
  276. ! scale from kg/s to kg/month
  277. field3d = field3d * sec_month ! kg / month
  278. hasData=1
  279. end if
  280. end if
  281. call Par_broadcast(hasData, status)
  282. IF_NOTOK_RETURN(status=1)
  283. if (hasData == 0) cycle sec
  284. ! ---------------------------
  285. ! CO2 emissions are provided as 2d data
  286. ! ---------------------------
  287. if (isRoot) then ! print total & regrid
  288. call msg_emis( amonth, trim(sectors_def(lsec)%prov)//' '//sectors_def(lsec)%name//' mass month', 'CO2', xmco2, sum(field3d(:,:,1)) )
  289. call coarsen_emission( 'CO2 '//sectors_def(lsec)%name, &
  290. nlon360, nlat180, field3d(:,:,1), wrk2D, add_field, status )
  291. IF_NOTOK_RETURN(status=1;deallocate(field3d))
  292. end if
  293. do region = 1, nregions
  294. call scatter(dgrid(region), co2_emis_2d(region,seccount2d)%surf, work(region)%d3(:,:,1), 0, status)
  295. IF_NOTOK_RETURN(status=1)
  296. end do
  297. end do sec ! sectors
  298. deallocate( field3d )
  299. do region = 1, nregions
  300. if (associated(wrk2D(region)%surf)) nullify(wrk2D(region)%surf)
  301. deallocate( work(region)%d3 )
  302. end do
  303. ! ok
  304. status = 0
  305. END SUBROUTINE EMISSION_CO2_DECLARE
  306. !EOC
  307. !--------------------------------------------------------------------------
  308. ! TM5 !
  309. !--------------------------------------------------------------------------
  310. !BOP
  311. !
  312. ! !IROUTINE: EMISSION_CO2_APPLY
  313. !
  314. ! !DESCRIPTION: Take monthly emissions, and
  315. ! - split them vertically
  316. ! - apply time splitting factors
  317. ! - add them to tracers (add_3d)
  318. !\\
  319. !\\
  320. ! !INTERFACE:
  321. !
  322. SUBROUTINE EMISSION_CO2_APPLY( region, status )
  323. !
  324. ! !USES:
  325. !
  326. use dims, only : okdebug, itaur, nsrce, tref
  327. use dims, only : im, jm, lm
  328. use datetime, only : tau2date
  329. use emission_data, only : emission_vdist_by_sector
  330. use emission_data, only : do_add_3d
  331. use chem_param, only : ico2, xmco2
  332. use emission_read, only : sectors_def, numb_sectors
  333. !
  334. ! !INPUT PARAMETERS:
  335. !
  336. integer, intent(in) :: region
  337. !
  338. ! !OUTPUT PARAMETERS:
  339. !
  340. integer, intent(out) :: status
  341. !
  342. ! !REVISION HISTORY:
  343. ! 1 Oct 2010 - Achim Strunk - AR5
  344. ! 26 Jun 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  345. !
  346. !EOP
  347. !------------------------------------------------------------------------
  348. !BOC
  349. character(len=*), parameter :: rname = mname//'/emission_co2_apply'
  350. integer, dimension(6) :: idater
  351. real :: dtime, fraction
  352. integer :: imr, jmr, lmr, lsec, i1, i2, j1, j2
  353. integer :: seccount2d, seccount3d
  354. type(d3_data) :: emis3d
  355. ! --- begin -----------------------------
  356. status = 0
  357. if(.not. has_emis) return
  358. if( okdebug ) then
  359. write(gol,*) 'start of emission_co2_apply'; call goPr
  360. end if
  361. call tau2date(itaur(region),idater)
  362. dtime=float(nsrce)/(2*tref(region)) !emissions are added in two steps...XYZECCEZYX.
  363. if(okdebug) then
  364. write(gol,*)'emission_co2_apply in region ',region,' at date: ',idater, ' with time step:', dtime
  365. call goPr
  366. end if
  367. ! get a working structure for 3d emissions
  368. call get_distgrid( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
  369. allocate( emis3d%d3(i1:i2,j1:j2,lm(region)) ) ; emis3d%d3 = 0.0
  370. ! count 2d and 3d sectors
  371. seccount2d = 0
  372. seccount3d = 0
  373. ! cycle over sectors
  374. do lsec = 1, numb_sectors
  375. if (count(used_providers.eq.sectors_def(lsec)%prov).eq.0) cycle
  376. ! default: no additional splitting
  377. fraction = 1.0
  378. seccount2d = seccount2d + 1
  379. emis3d%d3 = 0.0
  380. ! vertically distribute according to sector
  381. call emission_vdist_by_sector( sectors_def(lsec)%vdisttype, 'CO2', region, co2_emis_2d(region,seccount2d), emis3d, status )
  382. IF_NOTOK_RETURN(status=1;deallocate(emis3d%d3))
  383. ! add dataset according to sector and category
  384. call do_add_3d( region, ico2, i1, j1, emis3d%d3, xmco2, xmco2, status, fraction )
  385. IF_NOTOK_RETURN(status=1)
  386. end do
  387. deallocate( emis3d%d3 )
  388. if(okdebug) then
  389. write(gol,*) 'end of emission_co2_apply'; call goPr
  390. end if
  391. ! OK
  392. status = 0
  393. END SUBROUTINE EMISSION_CO2_APPLY
  394. !EOC
  395. END MODULE EMISSION_CO2