emission_co2.F90 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  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, okdebug
  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. logical, allocatable :: has_data_3d(:), has_data_2d(:)
  46. integer :: co2_2dsec, co2_3dsec
  47. !
  48. ! !REVISION HISTORY:
  49. ! 1 Oct 2010 - Achim Strunk - revamped for AR5
  50. ! 26 Jun 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  51. ! 14 May 2014 - T. van Noije - created CO2 version from CO version
  52. ! to be done: convert CMIP5 CO2 input files
  53. ! for emissions from fossil fuel use and land use
  54. ! into the same format as for the other trace species
  55. ! 23 March 2018 - T. van Noije - included CMIP6 anthropogenic emissions from CEDS
  56. !
  57. ! !REMARKS:
  58. !
  59. !EOP
  60. !------------------------------------------------------------------------
  61. CONTAINS
  62. !--------------------------------------------------------------------------
  63. ! TM5 !
  64. !--------------------------------------------------------------------------
  65. !BOP
  66. !
  67. ! !IROUTINE: EMISSION_CO2_INIT
  68. !
  69. ! !DESCRIPTION: Allocate memory to handle the emissions.
  70. !\\
  71. !\\
  72. ! !INTERFACE:
  73. !
  74. SUBROUTINE EMISSION_CO2_INIT( status )
  75. !
  76. ! !USES:
  77. !
  78. use dims, only : lm
  79. use emission_read, only : providers_def, numb_providers
  80. !
  81. ! !OUTPUT PARAMETERS:
  82. !
  83. integer, intent(out) :: status
  84. !
  85. ! !REVISION HISTORY:
  86. ! 1 Oct 2010 - Achim Strunk - v0
  87. ! 26 Jun 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  88. !
  89. !EOP
  90. !------------------------------------------------------------------------
  91. !BOC
  92. character(len=*), parameter :: rname = mname//'/Emission_CO2_Init'
  93. integer :: region
  94. integer :: imr, jmr, lmr, lsec, lprov, i1, i2, j1, j2
  95. ! --- begin --------------------------------------
  96. status = 0
  97. if(.not. has_emis) return
  98. ! nb of sectors
  99. co2_2dsec = 0
  100. co2_3dsec = 0
  101. do lprov = 1, numb_providers
  102. if (count(used_providers.eq.providers_def(lprov)%name)/=0) then
  103. co2_2dsec = co2_2dsec + providers_def(lprov)%nsect2d
  104. co2_3dsec = co2_3dsec + providers_def(lprov)%nsect3d
  105. endif
  106. enddo
  107. allocate( co2_emis_2d( nregions, co2_2dsec ) )
  108. allocate( co2_emis_3d( nregions, co2_3dsec ) )
  109. allocate( has_data_2d(co2_2dsec)) ; has_data_2d=.false.
  110. allocate( has_data_3d(co2_3dsec)) ; has_data_3d=.false.
  111. ! allocate information arrays (2d and 3d)
  112. do region=1,nregions
  113. CALL GET_DISTGRID( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
  114. lmr = lm(region)
  115. do lsec=1,co2_2dsec
  116. allocate( co2_emis_2d(region,lsec)%surf(i1:i2,j1:j2) )
  117. end do
  118. do lsec=1,co2_3dsec
  119. allocate( co2_emis_3d(region,lsec)%d3(i1:i2,j1:j2,lmr) )
  120. end do
  121. enddo
  122. ! ok
  123. status = 0
  124. END SUBROUTINE EMISSION_CO2_INIT
  125. !EOC
  126. !--------------------------------------------------------------------------
  127. ! TM5 !
  128. !--------------------------------------------------------------------------
  129. !BOP
  130. !
  131. ! !IROUTINE: EMISSION_CO2_DONE
  132. !
  133. ! !DESCRIPTION: Free memory after handling of the emissions.
  134. !\\
  135. !\\
  136. ! !INTERFACE:
  137. !
  138. SUBROUTINE EMISSION_CO2_DONE( status )
  139. !
  140. ! !OUTPUT PARAMETERS:
  141. !
  142. integer, intent(out) :: status
  143. !
  144. ! !REVISION HISTORY:
  145. ! 1 Oct 2010 - Achim Strunk - v0
  146. !
  147. !EOP
  148. !------------------------------------------------------------------------
  149. !BOC
  150. character(len=*), parameter :: rname = mname//'/Emission_CO2_Done'
  151. integer :: region, lsec
  152. ! --- begin --------------------------------------
  153. status = 0
  154. if(.not. has_emis) return
  155. do region = 1, nregions
  156. do lsec=1,co2_2dsec
  157. deallocate( co2_emis_2d(region,lsec)%surf )
  158. end do
  159. do lsec=1,co2_3dsec
  160. deallocate( co2_emis_3d(region,lsec)%d3 )
  161. end do
  162. end do
  163. deallocate( co2_emis_2d )
  164. deallocate( co2_emis_3d )
  165. deallocate( has_data_2d, has_data_3d)
  166. ! ok
  167. status = 0
  168. END SUBROUTINE EMISSION_CO2_DONE
  169. !EOC
  170. !--------------------------------------------------------------------------
  171. ! TM5 !
  172. !--------------------------------------------------------------------------
  173. !BOP
  174. !
  175. ! !IROUTINE: EMISSION_CO2_DECLARE
  176. !
  177. ! !DESCRIPTION: Opens, reads and evaluates input files (per month).
  178. ! Provides emissions on 2d/3d-arrays which are then added
  179. ! to mixing ratios in routine *apply.
  180. !\\
  181. !\\
  182. ! !INTERFACE:
  183. !
  184. SUBROUTINE EMISSION_CO2_DECLARE( status )
  185. !
  186. ! !USES:
  187. !
  188. use toolbox, only : coarsen_emission
  189. use dims, only : im, jm, lm, idate, sec_month, nlon360, nlat180, iglbsfc
  190. use chem_param, only : xmco2
  191. use emission_data, only : msg_emis
  192. ! ---------------- AR5 - ETC. --------------------
  193. use emission_data, only : emis_input_year_co2
  194. use emission_read, only : emission_ar5_regrid_aircraft
  195. use emission_read, only : emission_cmip6_ReadSector
  196. use emission_read, only : emission_ar5_ReadCO2
  197. use emission_read, only : sectors_def, numb_sectors
  198. use emission_read, only : ar5_dim_3ddata
  199. !
  200. ! !OUTPUT PARAMETERS:
  201. !
  202. integer, intent(out) :: status
  203. !
  204. ! !REVISION HISTORY:
  205. ! 1 Oct 2010 - Achim Strunk - adapted for AR5
  206. ! 26 Jun 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  207. !
  208. ! !REMARKS:
  209. !
  210. !EOP
  211. !------------------------------------------------------------------------
  212. !BOC
  213. character(len=*), parameter :: rname = mname//'/emission_co2_declare'
  214. integer :: region, hasData
  215. integer, parameter :: add_field=0
  216. integer, parameter :: amonth=2
  217. integer :: imr, jmr, lmr, lsec, i1, i2, j1, j2
  218. ! AR5
  219. real,dimension(:,:,:), allocatable :: field3d, field3d2
  220. type(d3_data), dimension(nregions) :: emis3d, work, work3d
  221. type(emis_data) :: wrk2D(nregions)
  222. integer :: seccount2d, seccount3d
  223. real :: emiss_total=0.
  224. ! --- begin -----------------------------------------
  225. status = 0
  226. if(.not. has_emis) return
  227. write(gol,'(" EMISS-INFO ------------- read CO2 emissions -------------")'); call goPr
  228. do region = 1, nregions
  229. do lsec=1,co2_2dsec
  230. co2_emis_2d(region,lsec)%surf = 0.0
  231. end do
  232. do lsec=1,co2_3dsec
  233. co2_emis_3d(region,lsec)%d3 = 0.0
  234. end do
  235. CALL GET_DISTGRID( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
  236. lmr = lm(region)
  237. allocate( work3d(region)%d3 (i1:i2,j1:j2, ar5_dim_3ddata) ) ; work3d(region)%d3 = 0.0
  238. allocate( emis3d(region)%d3 (i1:i2,j1:j2, lmr ) ) ; emis3d(region)%d3 = 0.0
  239. end do
  240. ! global arrays for coarsening
  241. do region = 1, nregions
  242. if (isRoot)then
  243. allocate(work(region)%d3(im(region),jm(region),ar5_dim_3ddata))
  244. else
  245. allocate(work(region)%d3(1,1,1))
  246. end if
  247. enddo
  248. do region = 1, nregions
  249. wrk2D(region)%surf => work(region)%d3(:,:,1)
  250. end do
  251. ! --------------------------------
  252. ! do a loop over available sectors
  253. ! --------------------------------
  254. ! count 2d and 3d sectors
  255. seccount2d = 0
  256. seccount3d = 0
  257. ! always allocate here 3d data set (for 2d sectors it will be filled in first layer only)
  258. if (isRoot) then
  259. allocate( field3d( nlon360, nlat180, ar5_dim_3ddata ) ) ; field3d = 0.0
  260. else
  261. allocate( field3d( 1, 1, 1 ) )
  262. end if
  263. sec : do lsec = 1, numb_sectors
  264. if (count(used_providers.eq.sectors_def(lsec)%prov).eq.0) cycle
  265. field3d = 0.0
  266. if( sectors_def(lsec)%f3d ) then
  267. seccount3d = seccount3d + 1
  268. else
  269. seccount2d = seccount2d + 1
  270. end if
  271. if (isRoot) then ! READ
  272. select case( trim(sectors_def(lsec)%prov) )
  273. case( 'CMIP6' )
  274. call emission_cmip6_ReadSector( 'CO2', emis_input_year_co2, idate(2), lsec, field3d, status )
  275. IF_NOTOK_RETURN(status=1;deallocate(field3d))
  276. case( 'AR5' )
  277. call emission_ar5_ReadCO2( 'CO2', emis_input_year_co2, idate(2), lsec, field3d, status )
  278. IF_NOTOK_RETURN(status=1;deallocate(field3d))
  279. case('DUMMY')
  280. case default
  281. write(gol,*) "Error in buidling list of providers USED_PROVIDERS"; call goErr
  282. status=1; TRACEBACK; return
  283. end select
  284. ! nothing found???
  285. if( abs(sum(field3d)) < 100.*TINY(1.0) ) then
  286. if (okdebug) then
  287. write(gol,'("EMISS-INFO - no CO2 emissions found for ",a," ",a," for month ",i2 )') &
  288. trim(sectors_def(lsec)%prov), trim(sectors_def(lsec)%name), idate(2) ; call goPr
  289. endif
  290. hasData=0
  291. else
  292. if (okdebug) then
  293. write(gol,'("EMISS-INFO - found CO2 emissions for ",a," ",a," for month ",i2 )') &
  294. trim(sectors_def(lsec)%prov), trim(sectors_def(lsec)%name), idate(2) ; call goPr
  295. endif
  296. ! scale from kg/s to kg/month
  297. field3d = field3d * sec_month ! kg / month
  298. hasData=1
  299. end if
  300. end if
  301. call Par_broadcast(hasData, status)
  302. IF_NOTOK_RETURN(status=1)
  303. if (hasData == 0) then
  304. cycle sec
  305. else
  306. if ( sectors_def(lsec)%f3d ) then
  307. has_data_3d(seccount3d)=.true.
  308. else
  309. has_data_2d(seccount2d)=.true.
  310. end if
  311. end if
  312. ! Distinguish 2d/3d sectors
  313. if( sectors_def(lsec)%f3d ) then
  314. ! ---------------------------------------
  315. ! 3d data (AIRCRAFT), available for CMIP6
  316. ! ---------------------------------------
  317. if (isRoot) then
  318. ! write some numbers
  319. call msg_emis( amonth, trim(sectors_def(lsec)%prov), sectors_def(lsec)%name, 'CO2', xmco2, sum(field3d) )
  320. emiss_total = emiss_total + sum(field3d)
  321. ! distribute to work arrays in regions
  322. call Coarsen_Emission( 'CO2 '//trim(sectors_def(lsec)%name), nlon360, nlat180, ar5_dim_3ddata, &
  323. field3d, work, add_field, status )
  324. IF_NOTOK_RETURN(status=1)
  325. end if
  326. ! scatter, sum up on target array
  327. do region = 1, nregions
  328. call scatter(dgrid(region), work3d(region)%d3, work(region)%d3, 0, status)
  329. IF_NOTOK_RETURN( status=1 )
  330. CALL GET_DISTGRID( dgrid(region), I_STRT=i1, J_STRT=j1)
  331. ! aircraft data: regrid vertically to model layers
  332. call emission_ar5_regrid_aircraft( region, i1, j1, work3d(region)%d3, emis3d(region)%d3, status )
  333. IF_NOTOK_RETURN( status=1 )
  334. co2_emis_3d(region,seccount3d)%d3 = co2_emis_3d(region,seccount3d)%d3 + emis3d(region)%d3
  335. end do
  336. else ! ar5_sector is 2d
  337. ! ---------------------------
  338. ! 2d data
  339. ! ---------------------------
  340. if (isRoot) then ! print total & regrid
  341. call msg_emis( amonth, trim(sectors_def(lsec)%prov), sectors_def(lsec)%name, 'CO2', xmco2, sum(field3d(:,:,1)) )
  342. emiss_total = emiss_total + sum(field3d(:,:,1))
  343. call coarsen_emission( 'CO2 '//sectors_def(lsec)%name, &
  344. nlon360, nlat180, field3d(:,:,1), wrk2D, add_field, status )
  345. IF_NOTOK_RETURN(status=1;deallocate(field3d))
  346. end if
  347. do region = 1, nregions
  348. call scatter(dgrid(region), co2_emis_2d(region,seccount2d)%surf, work(region)%d3(:,:,1), 0, status)
  349. IF_NOTOK_RETURN(status=1)
  350. end do
  351. endif
  352. end do sec ! sectors
  353. ! write some numbers
  354. call msg_emis( amonth, 'TOTAL', '', 'CO2', xmco2, emiss_total )
  355. deallocate( field3d )
  356. do region = 1, nregions
  357. if (associated(wrk2D(region)%surf)) nullify(wrk2D(region)%surf)
  358. deallocate( work(region)%d3 )
  359. deallocate( work3d(region)%d3 )
  360. deallocate( emis3d(region)%d3 )
  361. end do
  362. ! check sectors found
  363. if( seccount2d /= co2_2dsec ) then
  364. write(gol,'(80("-"))') ; call goPr
  365. write(gol,'("ERROR: 2d sectors do not equal total number:",i4," /= ",i4," !")') seccount2d, co2_2dsec ; call goErr
  366. write(gol,'(80("-"))') ; call goPr
  367. status=1; return
  368. end if
  369. if( seccount3d /= co2_3dsec ) then
  370. write(gol,'(80("-"))') ; call goPr
  371. write(gol,'("ERROR: 3d sectors do not equal total number:",i4," /= ",i4," !")') seccount3d, co2_3dsec ; call goErr
  372. write(gol,'(80("-"))') ; call goPr
  373. status=1; return
  374. end if
  375. ! ok
  376. status = 0
  377. END SUBROUTINE EMISSION_CO2_DECLARE
  378. !EOC
  379. !--------------------------------------------------------------------------
  380. ! TM5 !
  381. !--------------------------------------------------------------------------
  382. !BOP
  383. !
  384. ! !IROUTINE: EMISSION_CO2_APPLY
  385. !
  386. ! !DESCRIPTION: Take monthly emissions, and
  387. ! - split them vertically
  388. ! - apply time splitting factors
  389. ! - add them to tracers (add_3d)
  390. !\\
  391. !\\
  392. ! !INTERFACE:
  393. !
  394. SUBROUTINE EMISSION_CO2_APPLY( region, status )
  395. !
  396. ! !USES:
  397. !
  398. use dims, only : itaur, nsrce, tref
  399. use dims, only : im, jm, lm
  400. use datetime, only : tau2date
  401. use emission_data, only : emission_vdist_by_sector
  402. use emission_data, only : do_add_3d
  403. use chem_param, only : ico2, xmco2
  404. use emission_read, only : sectors_def, numb_sectors
  405. !
  406. ! !INPUT PARAMETERS:
  407. !
  408. integer, intent(in) :: region
  409. !
  410. ! !OUTPUT PARAMETERS:
  411. !
  412. integer, intent(out) :: status
  413. !
  414. ! !REVISION HISTORY:
  415. ! 1 Oct 2010 - Achim Strunk - AR5
  416. ! 26 Jun 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  417. !
  418. !EOP
  419. !------------------------------------------------------------------------
  420. !BOC
  421. character(len=*), parameter :: rname = mname//'/emission_co2_apply'
  422. integer, dimension(6) :: idater
  423. real :: dtime, fraction
  424. integer :: imr, jmr, lmr, lsec, i1, i2, j1, j2
  425. integer :: seccount2d, seccount3d
  426. type(d3_data) :: emis3d
  427. ! --- begin -----------------------------
  428. status = 0
  429. if(.not. has_emis) return
  430. if( okdebug ) then
  431. write(gol,*) 'start of emission_co2_apply'; call goPr
  432. end if
  433. call tau2date(itaur(region),idater)
  434. dtime=float(nsrce)/(2*tref(region)) !emissions are added in two steps...XYZECCEZYX.
  435. if(okdebug) then
  436. write(gol,*)'emission_co2_apply in region ',region,' at date: ',idater, ' with time step:', dtime
  437. call goPr
  438. end if
  439. ! get a working structure for 3d emissions
  440. call get_distgrid( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
  441. allocate( emis3d%d3(i1:i2,j1:j2,lm(region)) ) ; emis3d%d3 = 0.0
  442. ! count 2d and 3d sectors
  443. seccount2d = 0
  444. seccount3d = 0
  445. ! cycle over sectors
  446. do lsec = 1, numb_sectors
  447. if (count(used_providers.eq.sectors_def(lsec)%prov).eq.0) cycle
  448. ! default: no additional splitting
  449. fraction = 1.0
  450. ! distinguish between 2d/3d sectors
  451. if( sectors_def(lsec)%f3d ) then
  452. seccount3d = seccount3d + 1
  453. if (.not.has_data_3d(seccount3d)) cycle
  454. emis3d%d3 = co2_emis_3d(region,seccount3d)%d3
  455. else
  456. seccount2d = seccount2d + 1
  457. if (.not.has_data_2d(seccount2d)) cycle
  458. emis3d%d3 = 0.0
  459. ! vertically distribute according to sector
  460. call emission_vdist_by_sector( sectors_def(lsec)%vdisttype, 'CO2', region, co2_emis_2d(region,seccount2d), emis3d, status )
  461. IF_NOTOK_RETURN(status=1;deallocate(emis3d%d3))
  462. end if
  463. ! add dataset according to sector and category
  464. call do_add_3d( region, ico2, i1, j1, emis3d%d3, xmco2, xmco2, status, fraction )
  465. IF_NOTOK_RETURN(status=1)
  466. end do
  467. deallocate( emis3d%d3 )
  468. if(okdebug) then
  469. write(gol,*) 'end of emission_co2_apply'; call goPr
  470. end if
  471. ! OK
  472. status = 0
  473. END SUBROUTINE EMISSION_CO2_APPLY
  474. !EOC
  475. END MODULE EMISSION_CO2