budget_global.F90 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261
  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. #include "output.inc"
  8. !
  9. !-----------------------------------------------------------------------------
  10. ! TM5 !
  11. !-----------------------------------------------------------------------------
  12. !BOP
  13. !
  14. ! !MODULE: BUDGET_GLOBAL
  15. !
  16. ! !DESCRIPTION: This module holds most of the budget variables (see
  17. ! wet_deposition for exceptions).
  18. !
  19. ! Budgets are defined for a set of horizontal regions, split vertically, and
  20. ! available for each transported tracers. In the module:
  21. !
  22. ! o defines the budget output filename
  23. ! o defines the horizontal 'regions' for which a budgets are calculated
  24. ! e.g. Europe, HNH, Africa, zonal bands
  25. ! o defines the vertical split of the budgets
  26. ! e.g. boundary layer, free troposphere, stratosphere
  27. ! o routines to compute the transport budgets (advx, advy, advz, conv)
  28. ! o sets up the possibility to calculate transport fluxes in/out a
  29. ! predefined XY, XZ, and YZ planes (2 of each => define a box)
  30. ! o other budget terms (emission, deposition, etc.) can be added to the budget file
  31. !
  32. !\\
  33. !\\
  34. ! !INTERFACE:
  35. !
  36. MODULE BUDGET_GLOBAL
  37. !
  38. ! !USES:
  39. !
  40. use GO, only : gol, goErr, goPr
  41. use dims, only : im, jm, lm, idatei, idatee, nregions, region_name
  42. use dims, only : itau, idate, dx, dy, xref, yref, xbeg, ybeg
  43. use chem_param, only : ntracet, ntrace, names, ra
  44. use tm5_distgrid, only : dgrid, Get_DistGrid, reduce, gather
  45. IMPLICIT NONE
  46. PRIVATE
  47. !
  48. ! !PUBLIC MEMBER FUNCTIONS:
  49. !
  50. public :: init_budget_global ! initialize and allocate variables
  51. public :: done_budget_global ! final computation, write budgets to file
  52. public :: budget_transportg ! evaluate advection/convection budgets
  53. public :: budget_displayg ! print out budget of tracer #1
  54. !
  55. ! !PUBLIC DATA MEMBERS:
  56. !
  57. character(len=256), public :: budget_file_global ! name of budget output file
  58. integer, public, parameter :: nbudg = 7 ! # horizontal budget regions (h-budgets)
  59. integer, public, parameter :: nbud_vg = 4 ! # vertical budget regions (v-budgets)
  60. logical, public :: apply_budget_global = .false. ! compute budgets
  61. logical, public :: apply_budget_global_flux = .false. ! compute extra fluxes
  62. logical, public :: NHAB ! Non-Horizontally-Aggregated-Budgets (if true (default), writes [im,jm,nbud_vg] budgets
  63. ! which are available in the full chemistry (proj/cbm4 & proj/cb05)
  64. real, public, dimension(nbudg, nbud_vg, ntracet) :: budconvg ! convection budget
  65. real, public, dimension(nregions) :: init_mass = 0.0 ! tracer #1 : initial mass (meaningful on root only)
  66. real, public, dimension(nregions) :: sum_update = 0.0 ! tracer #1 :
  67. real, public, dimension(nregions) :: sum_advection = 0.0 ! tracer #1 : mass change thru advection (meaningful on root only)
  68. integer, public, dimension(lm(1)) :: nzon_vg ! vertical budget code of each level
  69. integer, public, dimension(nregions) :: iflux1, iflux2 ! I index of YZ plane where flux flowing in from west
  70. integer, public, dimension(nregions) :: jflux1, jflux2 ! J index of XZ plane where flux flowing in from south
  71. integer, public, dimension(nregions) :: lflux1, lflux2 ! L index of XY plane where flux flowing in from below
  72. !
  73. ! !PUBLIC TYPES:
  74. !
  75. type, public :: budg_data
  76. ! holds horizontal budget code of each cell (1:SH 90-30, 2:S30-N30, 3:NH 30-90, 4: Europe...)
  77. integer, dimension(:,:), pointer :: nzong
  78. end type budg_data
  79. type(budg_data), public, dimension(nregions), target :: budg_dat ! horizontal budget codes
  80. type, public :: budflux_data
  81. ! fluxes of all species through some predefined slices:
  82. real, dimension(:,:,:), pointer :: flux_x1 ! (jm,lm,ntracet)
  83. real, dimension(:,:,:), pointer :: flux_x2 ! (jm,lm,ntracet)
  84. real, dimension(:,:,:), pointer :: flux_y1 ! (im,lm,ntracet)
  85. real, dimension(:,:,:), pointer :: flux_y2 ! (im,lm,ntracet)
  86. real, dimension(:,:,:), pointer :: flux_z1 ! (im,jm,ntracet)
  87. real, dimension(:,:,:), pointer :: flux_z2 ! (im,jm,ntracet)
  88. end type budflux_data
  89. type(budflux_data), public, dimension(nregions), target :: budget_flux
  90. type(budflux_data), dimension(nregions), target :: budget_flux_all
  91. !
  92. ! !PRIVATE DATA MEMBERS:
  93. !
  94. real, dimension(nbudg, nbud_vg, ntracet) :: rmoldg, rmnewg ! work arrays (old/new rm)
  95. real, dimension(nbudg, nbud_vg, ntracet) :: budconcg ! final concentrations (end run)
  96. real, dimension(nbudg, nbud_vg, ntracet) :: budinig ! initial concentrations (begin run)
  97. real, dimension(nbudg, nbud_vg, ntracet) :: budchngg = 0.0 ! change of concentration b/w end-begin
  98. real, dimension(nbudg, nbud_vg, ntracet) :: budadvxg ! advection-x budget
  99. real, dimension(nbudg, nbud_vg, ntracet) :: budadvyg ! advection-y budget
  100. real, dimension(nbudg, nbud_vg, ntracet) :: budadvzg ! advection-z budget
  101. character(len=20), dimension(nbudg) :: zone_nameg ! name of horizontal budget regions
  102. character(len=20), dimension(nbud_vg) :: zone_namvg ! name of vertical budget regions
  103. integer :: lon_in, lon_out, lat_in, lat_out ! read box boundaries for extra fluxes
  104. character(len=*), parameter :: mname = 'budget_global' ! module name
  105. !
  106. ! !REVISION HISTORY:
  107. ! 28 Feb 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  108. !
  109. ! !REMARKS:
  110. ! (1) All processors compute the same aggregated budgets in case of MPI, but
  111. ! account only for the contribution of their own tile, if any. MPI
  112. ! reduction is used to sum up contributions.
  113. !
  114. !EOP
  115. !------------------------------------------------------------------------
  116. CONTAINS
  117. !--------------------------------------------------------------------------
  118. ! TM5 !
  119. !--------------------------------------------------------------------------
  120. !BOP
  121. !
  122. ! !IROUTINE: INI_ZONEG
  123. !
  124. ! !DESCRIPTION: set structure of user-defined "budget regions"
  125. !\\
  126. !\\
  127. ! !INTERFACE:
  128. !
  129. SUBROUTINE INI_ZONEG ( status )
  130. !
  131. ! !USES:
  132. !
  133. use GO , only : TrcFile, Init, Done, ReadRc
  134. use global_data, only : outdir, rcfile
  135. use toolbox , only : lvlpress
  136. use partools , only : isRoot
  137. #ifdef with_hdf4
  138. use file_hdf, only : THdfFile, TSds
  139. use file_hdf, only : Init, Done, WriteAttribute, WriteData
  140. #endif
  141. !
  142. ! !OUTPUT PARAMETERS:
  143. !
  144. integer, intent(out) :: status
  145. !
  146. ! !REVISION HISTORY:
  147. ! 28 Feb 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  148. !
  149. ! !REMARKS:
  150. !
  151. !EOP
  152. !------------------------------------------------------------------------
  153. !BOC
  154. #ifdef with_hdf4
  155. type(THdfFile) :: io
  156. type(TSds) :: sds
  157. #endif
  158. integer :: i1, i2, j1, j2, i, j, n, nix, niy, region
  159. integer :: ilvl1, ilvl2, ilvl3
  160. real :: psurf, plev, rlat, rlon
  161. real :: dyr, dxr, lats ! made real instead of integer to handle hi-res regions
  162. integer, allocatable :: gbl_data(:,:)
  163. type(TrcFile) :: rcF
  164. character(len=256) :: fname
  165. character(len=*), parameter :: rname = mname//'/ini_zong'
  166. ! ------- Compute budgets and extra fluxes ?
  167. #ifdef with_budgets
  168. apply_budget_global = .true.
  169. #endif
  170. if (.not.apply_budget_global) return
  171. call Init( rcF, rcfile, status )
  172. IF_NOTOK_RETURN(status=1)
  173. call ReadRc(rcF, 'apply.budget.global.flux', apply_budget_global_flux, status, default=.false.)
  174. IF_ERROR_RETURN(status=1)
  175. if (apply_budget_global_flux) then
  176. ! Example Europe: lat_in = 34, lat_out = 62, lon_in = -12, lon_out = 36
  177. call ReadRc(rcF, 'budget.global.flux.lon_in', lon_in, status )
  178. IF_NOTOK_RETURN(status=1)
  179. call ReadRc(rcF, 'budget.global.flux.lon_out', lon_out, status )
  180. IF_NOTOK_RETURN(status=1)
  181. call ReadRc(rcF, 'budget.global.flux.lat_in', lat_in, status )
  182. IF_NOTOK_RETURN(status=1)
  183. call ReadRc(rcF, 'budget.global.flux.lat_out', lat_out, status )
  184. IF_NOTOK_RETURN(status=1)
  185. endif
  186. call ReadRc(rcF, 'write.column.budgets', NHAB, status, default=.true.)
  187. IF_ERROR_RETURN(status=1)
  188. call Done( rcF, status )
  189. IF_NOTOK_RETURN(status=1)
  190. ! -------- Fill budgets name, code and vertical indices
  191. region = 1
  192. zone_namvg(1)='BL'
  193. zone_namvg(2)='850-500hPa'
  194. zone_namvg(3)='500-100hPa'
  195. zone_namvg(4)='100-0hPa'
  196. zone_nameg(1)='SH 90-30'
  197. zone_nameg(2)='30S-30N '
  198. zone_nameg(3)='NH 90-30'
  199. zone_nameg(4)='Europe'
  200. zone_nameg(5)='N-america'
  201. zone_nameg(6)='Asia'
  202. zone_nameg(7)='Africa'
  203. if ( isRoot ) then
  204. write(gol,'(A)') '-----------------------------------------------'; call goPr
  205. write(gol,'(A)') 'Horizontal definition of budget regions '; call goPr
  206. write(gol,'(A)') '-----------------------------------------------'; call goPr
  207. do i=1,nbudg
  208. write(gol,'(A,i4,4x,A)') 'Budget region:',i,zone_nameg(i); call goPr
  209. enddo
  210. !write(gol,'(A)') '-----------------------------------------------'; call goPr
  211. endif
  212. ! Associate a v-budget code to each level
  213. psurf = 98400.0
  214. plev = 85000.0 ; ilvl1 = lvlpress(region,plev, psurf)
  215. plev = 50000.0 ; ilvl2 = lvlpress(region,plev, psurf)
  216. plev = 10000.0 ; ilvl3 = lvlpress(region,plev, psurf)
  217. nzon_vg(1:ilvl1) = 1 !boundary layer
  218. nzon_vg(ilvl1+1:ilvl2)= 2 !850-->500 hPa
  219. nzon_vg(ilvl2+1:ilvl3)= 3 !500-->100 hPa
  220. nzon_vg(ilvl3+1:lm(1))= 4 !100 hPa-->TOA
  221. if ( isRoot ) then
  222. write(gol,'(A)') '-----------------------------------------------'; call goPr
  223. write(gol,'(A)') 'Distribution models levels over budget levels '; call goPr
  224. write(gol,'(A)') '-----------------------------------------------'; call goPr
  225. write(gol,'(A,A20,i4,A3,i4)') 'Budget level 1:', zone_namvg(1), 1, '...',ilvl1 ; call goPr
  226. write(gol,'(A,A20,i4,A3,i4)') 'Budget level 2:', zone_namvg(2), ilvl1+1,'...',ilvl2 ; call goPr
  227. write(gol,'(A,A20,i4,A3,i4)') 'Budget level 3:', zone_namvg(3), ilvl2+1,'...',ilvl3 ; call goPr
  228. write(gol,'(A,A20,i4,A3,i4)') 'Budget level 4:', zone_namvg(4), ilvl3+1,'...',lm(1) ; call goPr
  229. write(gol,'(A)') '-----------------------------------------------'; call goPr
  230. endif
  231. if (apply_budget_global_flux) then ! Limited to free troposphere
  232. lflux1(:) = ilvl1+1 ! where to calculate the vertical flux (1 = BL->FT)
  233. lflux2(:) = ilvl2+1 ! where to calculate the vertical flux (2 = FT->UFT)
  234. endif
  235. !---------- Allocate/fill arrays w/r/t horizontal definitions
  236. REG: do n=1,nregions
  237. call Get_DistGrid( dgrid(n), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
  238. ! allocate horizontal budget code :
  239. allocate( budg_dat(n)%nzong(i1:i2,j1:j2))
  240. ! allocate flux data:
  241. if (apply_budget_global_flux) then
  242. allocate( budget_flux(n)%flux_x1(j1:j2,lm(n),ntracet))
  243. allocate( budget_flux(n)%flux_y1(i1:i2,lm(n),ntracet))
  244. allocate( budget_flux(n)%flux_z1(i1:i2,j1:j2,ntracet))
  245. allocate( budget_flux(n)%flux_x2(j1:j2,lm(n),ntracet))
  246. allocate( budget_flux(n)%flux_y2(i1:i2,lm(n),ntracet))
  247. allocate( budget_flux(n)%flux_z2(i1:i2,j1:j2,ntracet))
  248. if (isRoot) then
  249. allocate( budget_flux_all(n)%flux_x1(jm(n),lm(n),ntracet))
  250. allocate( budget_flux_all(n)%flux_y1(im(n),lm(n),ntracet))
  251. allocate( budget_flux_all(n)%flux_z1(im(n),jm(n),ntracet))
  252. else
  253. allocate( budget_flux_all(n)%flux_x1(1,1,1))
  254. allocate( budget_flux_all(n)%flux_y1(1,1,1))
  255. allocate( budget_flux_all(n)%flux_z1(1,1,1))
  256. end if
  257. budget_flux(n)%flux_x1(:,:,:) = 0.0
  258. budget_flux(n)%flux_y1(:,:,:) = 0.0
  259. budget_flux(n)%flux_z1(:,:,:) = 0.0
  260. budget_flux(n)%flux_x2(:,:,:) = 0.0
  261. budget_flux(n)%flux_y2(:,:,:) = 0.0
  262. budget_flux(n)%flux_z2(:,:,:) = 0.0
  263. endif
  264. dyr = dy/yref(n)
  265. dxr = dx/xref(n)
  266. ! Fill horizontal budget codes for zonal bands
  267. do j=j1,j2
  268. lats = ybeg(n) + (j-1)*dyr
  269. ! PREV: not correct with resolutions less than 1 degree
  270. ! select case(lats)
  271. ! case(-90:-31)
  272. ! budg_dat(n)%nzong(:,j) = 3 !SH 90-30
  273. ! case(-30:29)
  274. ! budg_dat(n)%nzong(:,j) = 2 !-30->30
  275. ! case(30:90)
  276. ! budg_dat(n)%nzong(:,j) = 1 !NH 30-90
  277. ! case default
  278. ! write (gol,'(A)') 'ini_zoneg: Wrong latitude in budget routine' ; call goErr
  279. ! IF_NOTOK_RETURN(status=1)
  280. ! end select
  281. if ( lats >= -90. .and. lats < -30.) then
  282. budg_dat(n)%nzong(:,j) = 3 !SH 90-30
  283. elseif ( lats >= -30. .and. lats < 30.) then
  284. budg_dat(n)%nzong(:,j) = 2 !-30->30
  285. elseif ( lats >= 30. .and. lats < 90.) then
  286. budg_dat(n)%nzong(:,j) = 1 !NH 30-90
  287. else
  288. write (gol,'(A)') 'ini_zoneg: Wrong latitude in budget routine' ; call goErr
  289. IF_NOTOK_RETURN(status=1)
  290. end if
  291. end do
  292. ! Fill horizontal budget codes for continents : Europe, NAM, Asia, Africa
  293. do j=j1,j2
  294. rlat = ybeg(n) + (float(j)-0.5)*dyr
  295. do i=i1,i2
  296. rlon = xbeg(n) + (float(i)-0.5)*dxr
  297. if(rlon > lon_in .and. rlon < lon_out .and. rlat > lat_in .and. rlat < lat_out) then
  298. budg_dat(n)%nzong(i,j) = 4 ! EUROPE
  299. elseif(rlon > -126. .and. rlon < -66. .and. rlat > 22. .and. rlat < 62.) then
  300. budg_dat(n)%nzong(i,j) = 5 ! NAM
  301. elseif(rlon > 72. .and. rlon < 150. .and. rlat > -10. .and. rlat < 50.) then
  302. budg_dat(n)%nzong(i,j) = 6 ! Asia
  303. elseif(rlon > -18. .and. rlon < 48. .and. rlat > -34. .and. rlat < 34.) then
  304. budg_dat(n)%nzong(i,j) = 7 ! Africa
  305. endif
  306. enddo
  307. enddo
  308. ! --- Calculate in each region where to calculate the flux:
  309. !
  310. ! Get the index of the flux planes. The plane is always exactly between cells.
  311. ! The cell i-index east of the YZ-plane will be put in iflux(n) (for each region).
  312. ! iflux1 is the western plan (lon_in) and iflux2 is the eastern plane (lon_out).
  313. ! The same way jflux1 and jflux2 will become the j-index of the cells just north
  314. ! of the XZ-planes, etc.
  315. !
  316. if (apply_budget_global_flux) then
  317. jflux1(n)=0 ; jflux2(n)=0
  318. iflux1(n)=0 ; iflux2(n)=0
  319. do j=1,jm(n)
  320. ! rlat = ybeg(n) + (float(j)-0.5)*dyr
  321. ! Example Europe: lat_in = 34, lat_out = 62, lon_in = -12, lon_out = 36
  322. if( nint(ybeg(n) + float(j-1)*dyr) == lat_in) jflux1(n) = j
  323. if( nint(ybeg(n) + float(j-1)*dyr) == lat_out) jflux2(n) = j
  324. !if( nint(ybeg(n) + float(j)*dyr) == 62) jflux2(n) = j !CMK corrected
  325. enddo
  326. do i=1,im(n)
  327. ! rlon = xbeg(n) + (float(i)-0.5)*dxr
  328. if( nint(xbeg(n) + float(i-1)*dxr) == lon_in) iflux1(n) = i
  329. if( nint(xbeg(n) + float(i-1)*dxr) == lon_out) iflux2(n) = i ! corrected CMK
  330. !cmk if( nint(xbeg(n) + float(i)*dxr) == 36) iflux2(n) = i ! corrected CMK
  331. enddo
  332. endif
  333. ! --- Write the budgets regional definition to HDF file:
  334. if ( isRoot ) then
  335. allocate( gbl_data(im(n),jm(n)))
  336. else
  337. allocate( gbl_data(1,1))
  338. end if
  339. call gather( dgrid(n), budg_dat(n)%nzong, gbl_data, 0, status)
  340. #ifdef with_hdf4
  341. if ( isRoot ) then
  342. write (fname,'(a,"/regionsg_",a,".hdf")') trim(outdir), trim(region_name(n))
  343. call Init(io,fname,'create',status)
  344. IF_NOTOK_RETURN(status=1)
  345. call WriteAttribute(io, 'im', im(n), status)
  346. call WriteAttribute(io, 'jm', jm(n), status)
  347. call WriteAttribute(io, 'lm', lm(n), status)
  348. call Init(Sds, io, 'region_global', (/im(n),jm(n)/), 'integer(4)', status)
  349. IF_NOTOK_RETURN(status=1)
  350. call WriteData(Sds, gbl_data, status)
  351. IF_NOTOK_RETURN(status=1)
  352. call Done(Sds,status)
  353. IF_NOTOK_RETURN(status=1)
  354. call Done(io,status)
  355. IF_NOTOK_RETURN(status=1)
  356. end if
  357. #endif
  358. deallocate(gbl_data)
  359. end do REG
  360. ! Filename for budget data (include time range: budget_2001010100_2001020100_global.hdf)
  361. write (budget_file_global,'(a,"/budget_",i4.4,3i2.2,"_",i4.4,3i2.2,"_",a,".hdf")') &
  362. trim(outdir), idatei(1:4), idatee(1:4), 'global'
  363. #ifdef with_hdf4
  364. if ( isRoot ) then
  365. !write(gol,'(A )') '----------------------------------------------------'; call goPr
  366. write(gol,'(A,A)') 'Budget output file:', trim(budget_file_global); call goPr
  367. write(gol,'(A )') '----------------------------------------------------'; call goPr
  368. endif
  369. #else
  370. write(gol,'(A)') 'Budget will **NOT** be written - Requires HDF4'; call goPr
  371. write(gol,'(A)') '----------------------------------------------'; call goPr
  372. #endif
  373. ! OK
  374. status = 0
  375. END SUBROUTINE INI_ZONEG
  376. !EOC
  377. !--------------------------------------------------------------------------
  378. ! TM5 !
  379. !--------------------------------------------------------------------------
  380. !BOP
  381. !
  382. ! !IROUTINE: INIT_BUDGET_GLOBAL
  383. !
  384. ! !DESCRIPTION: initialize budgets
  385. !\\
  386. !\\
  387. ! !INTERFACE:
  388. !
  389. SUBROUTINE INIT_BUDGET_GLOBAL ( status )
  390. !
  391. ! !USES:
  392. !
  393. use ParTools, only : isRoot
  394. use global_data, only : region_dat, mass_dat
  395. !
  396. ! !OUTPUT PARAMETERS:
  397. !
  398. integer, intent(out) :: status
  399. !
  400. ! !REVISION HISTORY:
  401. ! 28 Feb 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  402. !
  403. !EOP
  404. !------------------------------------------------------------------------
  405. !BOC
  406. real,dimension(:,:,:,:),pointer :: rm
  407. integer,dimension(:,:) ,pointer :: zoomed, edge
  408. integer :: nzone, nzone_v, region
  409. integer :: i,j,l,n, i1,i2,j1,j2
  410. character(len=*), parameter :: rname = mname//'/init_budget_global'
  411. ! --- begin --------------------------------
  412. ! first set up the budget regions, and extra info from rcfile
  413. call ini_zoneg( status )
  414. IF_NOTOK_RETURN(status=1)
  415. ! reset budget variables
  416. budconcg = 0.
  417. budinig = 0.
  418. budconvg = 0.0
  419. budadvxg = 0.0
  420. budadvyg = 0.0
  421. budadvzg = 0.0
  422. REG: do region = 1, nregions
  423. rm => mass_dat(region)%rm
  424. zoomed => region_dat(region)%zoomed
  425. edge => region_dat(region)%edge
  426. call Get_DistGrid( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
  427. ! Tracer #1 init budgets
  428. call REDUCE( dgrid(region), rm(:,:,:,1), mass_dat(region)%halo, 'SUM', init_mass(region), status)
  429. IF_NOTOK_RETURN(status=1)
  430. sum_update(region) = 0.0
  431. sum_advection(region) = 0.0
  432. !
  433. ! initialise budinig
  434. !
  435. do n=1,ntracet
  436. do l=1,lm(region)
  437. nzone_v=nzon_vg(l) ! vertical bud code
  438. do j=j1,j2
  439. do i=i1,i2
  440. !skip zoomed part of the region
  441. if ( zoomed(i,j) /= region .or. edge(i,j) >= 1 ) cycle
  442. ! include the edges....parent takes care!
  443. nzone = budg_dat(region)%nzong(i,j)
  444. budinig(nzone, nzone_v, n) = budinig(nzone, nzone_v, n) + &
  445. rm(i,j,l,n)/ra(n)*1000.
  446. end do !i
  447. end do !j
  448. end do !l
  449. end do !n
  450. nullify(rm)
  451. nullify(zoomed)
  452. nullify(edge)
  453. enddo REG
  454. ! ok
  455. status = 0
  456. END SUBROUTINE INIT_BUDGET_GLOBAL
  457. !EOC
  458. !--------------------------------------------------------------------------
  459. ! TM5 !
  460. !--------------------------------------------------------------------------
  461. !BOP
  462. !
  463. ! !IROUTINE: DONE_BUDGET_GLOBAL
  464. !
  465. ! !DESCRIPTION: compute concentration change b/w beginning and end of the
  466. ! run; write budgets to output file.
  467. !\\
  468. !\\
  469. ! !INTERFACE:
  470. !
  471. SUBROUTINE DONE_BUDGET_GLOBAL ( status )
  472. !
  473. ! !USES:
  474. !
  475. use ParTools, only : isRoot, par_reduce_element, par_barrier
  476. use global_data, only : region_dat, mass_dat
  477. #ifdef with_hdf4
  478. use file_hdf, only : THdfFile, TSds
  479. use file_hdf, only : Done, WriteAttribute, Init, WriteData, SetDim
  480. #endif
  481. use tm5_distgrid, only : gather_i_band, gather_j_band
  482. !
  483. ! !OUTPUT PARAMETERS:
  484. !
  485. integer, intent(out) :: status
  486. !
  487. ! !REVISION HISTORY:
  488. ! 28 Feb 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  489. !
  490. !EOP
  491. !------------------------------------------------------------------------
  492. !BOC
  493. real, dimension(:,:,:,:), pointer :: rm
  494. integer, dimension(:,:) , pointer :: zoomed, edge
  495. integer :: nzone, nzone_v, region
  496. integer :: i,j,l,n, i1,i2,j1,j2
  497. #ifdef with_hdf4
  498. type(THdfFile) :: io
  499. type(TSds) :: sds
  500. #endif
  501. ! Need these arrays to deal with buggy MPI implementations: if send and receive buffers
  502. ! are the same, you can get this error on some system:
  503. ! Fatal error in PMPI_Reduce: Invalid buffer pointer, error stack:
  504. ! PMPI_Reduce(1701): MPI_Reduce(sbuf=0x1bae7a0 rbuf=0x1bae7a0, count=3060, MPI_DOUBLE_PRECISION, MPI_SUM, root=0, MPI_COMM_WORLD) failed
  505. ! PMPI_Reduce(1511): Buffers must not be aliased
  506. ! For MPICH2, this is a bug that was fixed in 2009 (http://lists.mcs.anl.gov/pipermail/mpich-discuss/2009-October/005804.html)
  507. ! but this is not the case for Intel MPI (the version used at KNMI)
  508. real, dimension(nbudg,nbud_vg,ntracet) :: budconcg_all
  509. real, dimension(nbudg,nbud_vg,ntracet) :: budchngg_all
  510. real, dimension(nbudg,nbud_vg,ntracet) :: budinig_all
  511. real, dimension(nbudg,nbud_vg,ntracet) :: budadvxg_all
  512. real, dimension(nbudg,nbud_vg,ntracet) :: budadvyg_all
  513. real, dimension(nbudg,nbud_vg,ntracet) :: budadvzg_all
  514. real, dimension(nbudg,nbud_vg,ntracet) :: budconvg_all
  515. ! --- const -------------------------------
  516. character(len=*), parameter :: rname = mname//'/done_budget_global'
  517. integer, parameter :: nproces=4 ! x,y,z, conv
  518. character(len=10), dimension(nproces),parameter :: proces_name=(/'names ','names ','names ','names '/)
  519. integer, dimension(nproces),parameter :: proces_nr = (/ ntracet, ntracet, ntracet, ntracet /)
  520. ! --- begin --------------------------------
  521. if (.not.apply_budget_global) return
  522. ! final concentrations
  523. budconcg = 0.0
  524. do region = 1, nregions
  525. call Get_DistGrid( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
  526. zoomed => region_dat(region)%zoomed
  527. edge => region_dat(region)%edge
  528. rm => mass_dat(region)%rm
  529. do n=1,ntracet
  530. do l=1,lm(region)
  531. nzone_v = nzon_vg(l)
  532. do j=j1,j2
  533. do i=i1,i2
  534. if (zoomed(i,j)/=region .or. edge(i,j) >= 1) cycle
  535. nzone = budg_dat(region)%nzong(i,j)
  536. budconcg(nzone, nzone_v, n) = budconcg(nzone, nzone_v, n) + &
  537. rm(i,j,l,n)/ra(n)*1000.
  538. end do !i
  539. end do !j
  540. end do !l
  541. end do !n
  542. nullify(rm)
  543. nullify(zoomed)
  544. nullify(edge)
  545. enddo
  546. ! Calculate concentrations change
  547. budchngg = budconcg - budinig
  548. ! Sum up contribution from each proc into root array
  549. call PAR_REDUCE_ELEMENT( budconcg, 'SUM', budconcg_all, status )
  550. IF_NOTOK_RETURN(status=1)
  551. call PAR_REDUCE_ELEMENT( budchngg, 'SUM', budchngg_all, status )
  552. IF_NOTOK_RETURN(status=1)
  553. call PAR_REDUCE_ELEMENT( budinig, 'SUM', budinig_all, status )
  554. IF_NOTOK_RETURN(status=1)
  555. call PAR_REDUCE_ELEMENT( budadvxg, 'SUM', budadvxg_all, status )
  556. IF_NOTOK_RETURN(status=1)
  557. call PAR_REDUCE_ELEMENT( budadvyg, 'SUM', budadvyg_all, status )
  558. IF_NOTOK_RETURN(status=1)
  559. call PAR_REDUCE_ELEMENT( budadvzg, 'SUM', budadvzg_all, status )
  560. IF_NOTOK_RETURN(status=1)
  561. call PAR_REDUCE_ELEMENT( budconvg, 'SUM', budconvg_all, status )
  562. IF_NOTOK_RETURN(status=1)
  563. #ifdef with_hdf4
  564. ! Write out budget file
  565. if ( isRoot ) then
  566. call Init(io, budget_file_global, 'create', status)
  567. IF_NOTOK_RETURN(status=1)
  568. call WriteAttribute(io, 'nregions', nregions, status)
  569. ! lib cannot handle kind=8
  570. ! call WriteAttribute(io, 'itau', itau, status)
  571. call WriteAttribute(io, 'nbud', nbudg, status)
  572. call WriteAttribute(io, 'nbud_v', nbud_vg, status)
  573. call WriteAttribute(io, 'ntrace', ntrace, status)
  574. call WriteAttribute(io, 'ntracet', ntracet, status)
  575. call WriteAttribute(io, 'idate', idate, status)
  576. call WriteAttribute(io, 'idatei', idatei, status)
  577. call WriteAttribute(io, 'idatee', idatee, status)
  578. call WriteAttribute(io, 'proces_nr', proces_nr, status)
  579. call WriteAttribute(io, 'proces_name', proces_name, status)
  580. call WriteAttribute(io, 'zone_name', zone_nameg, status)
  581. call WriteAttribute(io, 'zone_namv', zone_namvg, status)
  582. call WriteAttribute(io, 'names', names, status)
  583. if (apply_budget_global_flux) then
  584. call WriteAttribute(io, 'iflux1' , iflux1, status)
  585. call WriteAttribute(io, 'iflux2' , iflux2, status)
  586. call WriteAttribute(io, 'jflux1' , jflux1, status)
  587. call WriteAttribute(io, 'jflux2' , jflux2, status)
  588. call WriteAttribute(io, 'lflux1' , lflux1, status)
  589. call WriteAttribute(io, 'lflux2' , lflux2, status)
  590. endif
  591. IF_NOTOK_RETURN(status=1)
  592. call Init(Sds, io, 'budconc', (/nbudg, nbud_vg, ntracet/), 'real(8)', status)
  593. call SetDim(Sds, 0, 'nbudg', 'horizontal budget', (/(j, j=1,nbudg)/), status)
  594. call SetDim(Sds, 1, 'nbud_vg', 'vertical budget', (/(j, j=1,nbud_vg)/), status)
  595. call SetDim(Sds, 2, 'ntracet', 'tracer number', (/(j, j=1, ntracet)/), status)
  596. IF_NOTOK_RETURN(status=1)
  597. call WriteData(Sds, budconcg_all, status)
  598. IF_NOTOK_RETURN(status=1)
  599. call Done(Sds, status)
  600. IF_NOTOK_RETURN(status=1)
  601. call Init(Sds, io, 'budchng', (/nbudg, nbud_vg, ntracet/), 'real(8)', status)
  602. call SetDim(Sds, 0, 'nbudg', 'horizontal budget', (/(j, j=1,nbudg)/), status)
  603. call SetDim(Sds, 1, 'nbud_vg', 'vertical budget', (/(j, j=1,nbud_vg)/), status)
  604. call SetDim(Sds, 2, 'ntracet', 'tracer number', (/(j, j=1, ntracet)/), status)
  605. IF_NOTOK_RETURN(status=1)
  606. call WriteData(Sds, budchngg_all, status)
  607. IF_NOTOK_RETURN(status=1)
  608. call Done(Sds, status)
  609. IF_NOTOK_RETURN(status=1)
  610. call Init(Sds, io, 'budini', (/nbudg, nbud_vg, ntracet/), 'real(8)', status)
  611. call SetDim(Sds, 0, 'nbudg', 'horizontal budget', (/(j, j=1,nbudg)/), status)
  612. call SetDim(Sds, 1, 'nbud_vg', 'vertical budget', (/(j, j=1,nbud_vg)/), status)
  613. call SetDim(Sds, 2, 'ntracet', 'tracer number', (/(j, j=1, ntracet)/), status)
  614. IF_NOTOK_RETURN(status=1)
  615. call WriteData(Sds, budinig_all, status)
  616. IF_NOTOK_RETURN(status=1)
  617. call Done(Sds, status)
  618. IF_NOTOK_RETURN(status=1)
  619. call Init(Sds, io, 'budadvx', (/nbudg, nbud_vg, ntracet/), 'real(8)', status)
  620. call SetDim(Sds, 0, 'nbudg', 'horizontal budget', (/(j, j=1,nbudg)/), status)
  621. call SetDim(Sds, 1, 'nbud_vg', 'vertical budget', (/(j, j=1,nbud_vg)/), status)
  622. call SetDim(Sds, 2, 'ntracet', 'tracer number', (/(j, j=1, ntracet)/), status)
  623. IF_NOTOK_RETURN(status=1)
  624. call WriteData(Sds, budadvxg_all, status)
  625. IF_NOTOK_RETURN(status=1)
  626. call Done(Sds, status)
  627. IF_NOTOK_RETURN(status=1)
  628. call Init(Sds, io, 'budadvy', (/nbudg, nbud_vg, ntracet/), 'real(8)', status)
  629. call SetDim(Sds, 0, 'nbudg', 'horizontal budget', (/(j, j=1,nbudg)/), status)
  630. call SetDim(Sds, 1, 'nbud_vg', 'vertical budget', (/(j, j=1,nbud_vg)/), status)
  631. call SetDim(Sds, 2, 'ntracet', 'tracer number', (/(j, j=1,ntracet)/), status)
  632. IF_NOTOK_RETURN(status=1)
  633. call WriteData(Sds, budadvyg_all, status)
  634. IF_NOTOK_RETURN(status=1)
  635. call Done(Sds, status)
  636. IF_NOTOK_RETURN(status=1)
  637. call Init(Sds, io, 'budadvz', (/nbudg, nbud_vg, ntracet/), 'real(8)', status)
  638. call SetDim(Sds, 0, 'nbudg', 'horizontal budget', (/(j, j=1,nbudg)/), status)
  639. call SetDim(Sds, 1, 'nbud_vg', 'vertical budget', (/(j, j=1,nbud_vg)/), status)
  640. call SetDim(Sds, 2, 'ntracet', 'tracer number', (/(j, j=1,ntracet)/), status)
  641. IF_NOTOK_RETURN(status=1)
  642. call WriteData(Sds, budadvzg_all, status)
  643. IF_NOTOK_RETURN(status=1)
  644. call Done(Sds, status)
  645. IF_NOTOK_RETURN(status=1)
  646. call Init(Sds, io, 'budconv_nocp', (/nbudg, nbud_vg, ntracet/), 'real(8)', status)
  647. call SetDim(Sds, 0, 'nbudg', 'horizontal budget', (/(j, j=1,nbudg)/), status)
  648. call SetDim(Sds, 1, 'nbud_vg', 'vertical budget', (/(j, j=1,nbud_vg)/), status)
  649. call SetDim(Sds, 2, 'ntracet', 'tracer number', (/(j, j=1,ntracet)/), status)
  650. IF_NOTOK_RETURN(status=1)
  651. call WriteAttribute(Sds, 'comment', 'Convection budget not corrected for cp removal', status)
  652. IF_NOTOK_RETURN(status=1)
  653. call WriteData(Sds, budconvg_all, status)
  654. IF_NOTOK_RETURN(status=1)
  655. call Done(Sds, status)
  656. IF_NOTOK_RETURN(status=1)
  657. end if ! root
  658. #endif
  659. ! PLS: old unclear comment:
  660. ! Jottum. We have the chemistry. We have it before dry deposition.
  661. ! Let us not write it down. That is an idea
  662. ! Chemistry is done by budget_global
  663. ! Dry deposition is done by chemistry
  664. ! That is logical. We do not write chemistry here, because 'chemistry', the one
  665. ! about dry deposition can access it. And we need dry deposition (that is not accessible).
  666. ! because chemistry has been infested by dry deposition.
  667. ! Gather and write the extra flux through 2D slices
  668. if (apply_budget_global_flux) then
  669. do region=1,nregions
  670. call Get_DistGrid( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
  671. call GATHER_I_BAND( dgrid(region), budget_flux(region)%flux_x1, budget_flux_all(region)%flux_x1, status, iflux1(region) )
  672. IF_NOTOK_RETURN(status=1)
  673. #ifdef with_hdf4
  674. if (isRoot) then
  675. call Init(Sds, io, 'budget_flux_x1_'//region_name(region), (/jm(region),lm(region),ntracet/), 'real(4)', status)
  676. call SetDim(Sds, 0, 'jm_'//region_name(region), 'latitude index', (/(j, j=1,jm(region))/), status)
  677. call SetDim(Sds, 1, 'lm_'//region_name(region), 'layer index ', (/(j, j=1,lm(region))/), status)
  678. call SetDim(Sds, 2, 'ntracet', 'tracer number', (/(j, j=1,ntracet)/), status)
  679. IF_NOTOK_RETURN(status=1)
  680. call WriteData(Sds, budget_flux_all(region)%flux_x1, status)
  681. IF_NOTOK_RETURN(status=1)
  682. call Done(Sds, status)
  683. IF_NOTOK_RETURN(status=1)
  684. end if
  685. #endif
  686. call GATHER_I_BAND( dgrid(region), budget_flux(region)%flux_x2, budget_flux_all(region)%flux_x1, status, iflux2(region) )
  687. IF_NOTOK_RETURN(status=1)
  688. #ifdef with_hdf4
  689. if (isRoot) then
  690. call Init(Sds, io, 'budget_flux_x2_'//region_name(region), (/jm(region),lm(region),ntracet/), 'real(4)', status)
  691. call SetDim(Sds, 0, 'jm_'//region_name(region), 'latitude index', (/(j, j=1,jm(region))/), status)
  692. call SetDim(Sds, 1, 'lm_'//region_name(region), 'layer index ', (/(j, j=1,lm(region))/), status)
  693. call SetDim(Sds, 2, 'ntracet', 'tracer number', (/(j, j=1,ntracet)/), status)
  694. IF_NOTOK_RETURN(status=1)
  695. call WriteData(Sds, budget_flux_all(region)%flux_x1, status)
  696. IF_NOTOK_RETURN(status=1)
  697. call Done(Sds, status)
  698. IF_NOTOK_RETURN(status=1)
  699. end if
  700. #endif
  701. call GATHER_J_BAND( dgrid(region), budget_flux(region)%flux_y1, budget_flux_all(region)%flux_y1, status, jflux1(region) )
  702. IF_NOTOK_RETURN(status=1)
  703. #ifdef with_hdf4
  704. if (isRoot) then
  705. call Init(Sds, io, 'budget_flux_y1_'//region_name(region), (/im(region),lm(region),ntracet/), 'real(4)', status)
  706. call SetDim(Sds, 0, 'im_'//region_name(region), 'longitude index', (/(j, j=1,im(region))/), status)
  707. call SetDim(Sds, 1, 'lm_'//region_name(region), 'layer index ', (/(j, j=1,lm(region))/), status)
  708. call SetDim(Sds, 2, 'ntracet', 'tracer number', (/(j, j=1,ntracet)/), status)
  709. IF_NOTOK_RETURN(status=1)
  710. call WriteData(Sds, budget_flux_all(region)%flux_y1, status)
  711. IF_NOTOK_RETURN(status=1)
  712. call Done(Sds, status)
  713. IF_NOTOK_RETURN(status=1)
  714. end if
  715. #endif
  716. call GATHER_J_BAND( dgrid(region), budget_flux(region)%flux_y2, budget_flux_all(region)%flux_y1, status, jflux2(region) )
  717. IF_NOTOK_RETURN(status=1)
  718. #ifdef with_hdf4
  719. if (isRoot) then
  720. call Init(Sds, io, 'budget_flux_y2_'//region_name(region), (/im(region),lm(region),ntracet/), 'real(4)', status)
  721. call SetDim(Sds, 0, 'im_'//region_name(region), 'longitude index', (/(j, j=1,im(region))/), status)
  722. call SetDim(Sds, 1, 'lm_'//region_name(region), 'layer index ', (/(j, j=1,lm(region))/), status)
  723. call SetDim(Sds, 2, 'ntracet', 'tracer number', (/(j, j=1,ntracet)/), status)
  724. IF_NOTOK_RETURN(status=1)
  725. call WriteData(Sds, budget_flux_all(region)%flux_y1, status)
  726. IF_NOTOK_RETURN(status=1)
  727. call Done(Sds, status)
  728. IF_NOTOK_RETURN(status=1)
  729. end if
  730. #endif
  731. call GATHER( dgrid(region), budget_flux(region)%flux_z1, budget_flux_all(region)%flux_z1, 0, status )
  732. IF_NOTOK_RETURN(status=1)
  733. #ifdef with_hdf4
  734. if (isRoot) then
  735. call Init(Sds, io, 'budget_flux_z1_'//region_name(region), (/im(region),jm(region),ntracet/), 'real(4)', status)
  736. call SetDim(Sds, 0, 'im_'//region_name(region), 'longitude index', (/(j, j=1,im(region))/), status)
  737. call SetDim(Sds, 1, 'jm_'//region_name(region), 'latitude index ', (/(j, j=1,jm(region))/), status)
  738. call SetDim(Sds, 2, 'ntracet', 'tracer number', (/(j, j=1,ntracet)/), status)
  739. IF_NOTOK_RETURN(status=1)
  740. call WriteData(Sds, budget_flux_all(region)%flux_z1, status)
  741. IF_NOTOK_RETURN(status=1)
  742. call Done(Sds, status)
  743. IF_NOTOK_RETURN(status=1)
  744. end if
  745. #endif
  746. call GATHER( dgrid(region), budget_flux(region)%flux_z2, budget_flux_all(region)%flux_z1, 0, status )
  747. IF_NOTOK_RETURN(status=1)
  748. #ifdef with_hdf4
  749. if (isRoot) then
  750. call Init(Sds, io, 'budget_flux_z2_'//region_name(region), (/im(region),jm(region),ntracet/), 'real(4)', status)
  751. call SetDim(Sds, 0, 'im_'//region_name(region), 'longitude index', (/(j, j=1,im(region))/), status)
  752. call SetDim(Sds, 1, 'jm_'//region_name(region), 'latitude index ', (/(j, j=1,jm(region))/), status)
  753. call SetDim(Sds, 2, 'ntracet', 'tracer number', (/(j, j=1,ntracet)/), status)
  754. IF_NOTOK_RETURN(status=1)
  755. call WriteData(Sds, budget_flux_all(region)%flux_z1, status)
  756. IF_NOTOK_RETURN(status=1)
  757. call Done(Sds, status)
  758. IF_NOTOK_RETURN(status=1)
  759. end if
  760. #endif
  761. deallocate( budget_flux(region)%flux_x1)
  762. deallocate( budget_flux(region)%flux_y1)
  763. deallocate( budget_flux(region)%flux_z1)
  764. deallocate( budget_flux(region)%flux_x2)
  765. deallocate( budget_flux(region)%flux_y2)
  766. deallocate( budget_flux(region)%flux_z2)
  767. deallocate( budget_flux_all(region)%flux_x1)
  768. deallocate( budget_flux_all(region)%flux_y1)
  769. deallocate( budget_flux_all(region)%flux_z1)
  770. !KLUDGE (variable used in chemistr_done!) deallocate( budg_dat(region)%nzong)
  771. end do
  772. endif ! apply_budget_flux
  773. #ifdef with_hdf4
  774. if (isRoot) then
  775. call Done(io, status)
  776. IF_NOTOK_RETURN(status=1)
  777. end if
  778. #endif
  779. call budget_displayg ( status )
  780. IF_NOTOK_RETURN(status=1)
  781. ! OK
  782. status = 0
  783. END SUBROUTINE DONE_BUDGET_GLOBAL
  784. !EOC
  785. !--------------------------------------------------------------------------
  786. ! TM5 !
  787. !--------------------------------------------------------------------------
  788. !BOP
  789. !
  790. ! !IROUTINE: BUDGET_TRANSPORTG
  791. !
  792. ! !DESCRIPTION: evaluate advection/convection budgets
  793. !
  794. ! Routine is called before and after a transport step. The difference is used to
  795. ! calculate the budget. Problems occur with zoome regions. Here advection is
  796. ! applied by writing x-adges and y-edges (in put_xedges, put_yedges).
  797. ! Knowledge of the previous step is required to calculate the budget....
  798. !\\
  799. !\\
  800. ! !INTERFACE:
  801. !
  802. SUBROUTINE BUDGET_TRANSPORTG(region, stat, proces, prev_step)
  803. !
  804. ! !USES:
  805. !
  806. use dims, only : okdebug
  807. use global_data, only : region_dat, mass_dat
  808. !
  809. ! !INPUT PARAMETERS:
  810. !
  811. integer, intent(in) :: stat ! 0 before process, 1 after
  812. integer, intent(in) :: region
  813. character(len=*) :: proces ! current process (xyzvcs)
  814. character(len=*) :: prev_step ! previous process.
  815. !
  816. ! !REVISION HISTORY:
  817. ! 28 Feb 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  818. !
  819. !EOP
  820. !------------------------------------------------------------------------
  821. !BOC
  822. real, dimension(:,:,:,:), pointer :: rm
  823. integer, dimension(:,:), pointer :: zoomed, edge
  824. logical, dimension(:,:), allocatable :: skip_flag
  825. integer :: i,j,l,n, nzone, nzone_v, lmr, i1,j1,i2,j2
  826. ! ------ start
  827. if (.not.apply_budget_global) return
  828. rm => mass_dat(region)%rm
  829. zoomed => region_dat(region)%zoomed
  830. edge => region_dat(region)%edge
  831. lmr = lm(region)
  832. if ( okdebug ) then
  833. write(gol,*) 'budget_transportg: region, stat, proces, prev_step = ',&
  834. region, stat, proces,' ', prev_step ; call goPr
  835. end if
  836. call Get_DistGrid( dgrid(region), I_STRT=i1, I_STOP=i2, J_STRT=j1, J_STOP=j2 )
  837. !---------- flag
  838. allocate(skip_flag(i1:i2,j1:j2))
  839. skip_flag = .false.
  840. where ( zoomed /= region .or. edge >= 1 )
  841. skip_flag = .true.
  842. end where
  843. if ( proces(1:4) == 'advx' .and. prev_step /= 'y' ) then
  844. ! include y-edges if XYZ sequence
  845. where(edge >= 2)
  846. skip_flag = .false. !only remaining problem: reduced grid!
  847. end where
  848. else if ( proces(1:4) == 'advy' .and. prev_step /= 'x' ) then
  849. where ( edge == 1 .or. edge == 3 )
  850. skip_flag = .false.
  851. end where
  852. else if ( proces(1:4) == 'advz' .and. prev_step /= 'y' ) then
  853. ! zyx sequence: include interface
  854. where ( edge >= 1 )
  855. skip_flag = .false.
  856. end where
  857. else if ( proces(1:4) == 'conv' ) then ! always interface
  858. where ( edge >= 1 )
  859. skip_flag = .false.
  860. end where
  861. end if
  862. !----------- Calculate budget
  863. if ( stat == 0 ) then ! save current tracer concentrations
  864. rmoldg = 0.0
  865. do n=1, ntracet
  866. do l=1,lmr
  867. nzone_v = nzon_vg(l)
  868. do j=j1, j2
  869. do i=i1, i2
  870. if (skip_flag(i,j)) cycle
  871. nzone = budg_dat(region)%nzong(i,j)
  872. rmoldg(nzone,nzone_v,n) = &
  873. rmoldg(nzone,nzone_v,n) + rm(i,j,l,n)
  874. end do
  875. end do
  876. end do
  877. end do
  878. else ! new concentration and fill budget
  879. rmnewg = 0.0
  880. do n=1, ntracet
  881. do l=1,lmr
  882. nzone_v = nzon_vg(l)
  883. do j=j1,j2
  884. do i=i1,i2
  885. if (skip_flag(i,j)) cycle
  886. nzone=budg_dat(region)%nzong(i,j)
  887. rmnewg(nzone,nzone_v,n) = rmnewg(nzone,nzone_v,n) + rm(i,j,l,n)
  888. end do
  889. end do
  890. end do
  891. end do
  892. select CASE(proces(1:4))
  893. case('advx')
  894. do n=1, ntracet
  895. budadvxg(:,:,n) = budadvxg(:,:,n) + &
  896. (rmnewg(:,:,n)-rmoldg(:,:,n))/ra(n)*1e3
  897. end do
  898. case('advy')
  899. do n=1, ntracet
  900. budadvyg(:,:,n) = budadvyg(:,:,n) + &
  901. (rmnewg(:,:,n)-rmoldg(:,:,n))/ra(n)*1e3
  902. end do
  903. case('advz')
  904. do n=1, ntracet
  905. budadvzg(:,:,n) = budadvzg(:,:,n) + &
  906. (rmnewg(:,:,n)-rmoldg(:,:,n))/ra(n)*1e3
  907. end do
  908. case('conv')
  909. do n=1, ntracet
  910. budconvg(:,:,n) = budconvg(:,:,n) + &
  911. (rmnewg(:,:,n)-rmoldg(:,:,n))/ra(n)*1e3
  912. end do
  913. case default
  914. write(gol,*)'budget_transportg: no valid value for transport budget,', &
  915. ' budget not updated!'; call goPr
  916. end select
  917. end if
  918. deallocate(skip_flag)
  919. nullify(rm)
  920. nullify(zoomed)
  921. nullify(edge)
  922. END SUBROUTINE BUDGET_TRANSPORTG
  923. !EOC
  924. !--------------------------------------------------------------------------
  925. ! TM5 !
  926. !--------------------------------------------------------------------------
  927. !BOP
  928. !
  929. ! !IROUTINE: BUDGET_DISPLAYG
  930. !
  931. ! !DESCRIPTION: print out budget for tracer #1
  932. !\\
  933. !\\
  934. ! !INTERFACE:
  935. !
  936. SUBROUTINE BUDGET_DISPLAYG( status )
  937. !
  938. ! !USES:
  939. !
  940. use dims, only : nregions
  941. use chem_param, only : names
  942. use global_data, only : mass_dat
  943. use partools, only : isRoot, par_reduce
  944. #ifdef with_hdf4
  945. use file_hdf, only : THdfFile
  946. use file_hdf, only : Init, Done, WriteAttribute, WriteData
  947. #endif
  948. !
  949. ! !OUTPUT PARAMETERS:
  950. !
  951. integer, intent(out) :: status
  952. !
  953. ! !REVISION HISTORY:
  954. ! 28 Feb 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  955. !
  956. !EOP
  957. !------------------------------------------------------------------------
  958. !BOC
  959. #ifdef with_hdf4
  960. type(THdfFile) :: io
  961. #endif
  962. character(len=40) :: frmt
  963. integer :: region, imr, jmr, lmr
  964. real :: mass(nregions)
  965. character(len=*), parameter :: rname = mname//'/budget_displayg'
  966. real, dimension(nregions) :: sum_update_all, sum_advection_all
  967. ! --- begin --------------------------------
  968. if (.not.apply_budget_global) return
  969. if ( isRoot ) then
  970. write (gol,'("--------------------------------------------------------")'); call goPr
  971. write (gol,'(" Budget of tracer ",a," (kg) : ")') trim(names(1)) ; call goPr
  972. write (gol,'("--------------------------------------------------------")'); call goPr
  973. end if
  974. do region = 1, nregions
  975. call REDUCE( dgrid(region), mass_dat(region)%rm(:,:,:,1), mass_dat(region)%halo, 'SUM', mass(region), status)
  976. IF_NOTOK_RETURN(status=1)
  977. CALL PAR_REDUCE(sum_update(region), 'SUM', sum_update_all(region), status)
  978. IF_NOTOK_RETURN(status=1)
  979. CALL PAR_REDUCE(sum_advection(region), 'SUM', sum_advection_all(region), status)
  980. IF_NOTOK_RETURN(status=1)
  981. call get_format(mass(region),frmt)
  982. if ( isRoot ) then
  983. !write (gol,'("Region ",i3)') region; call goPr
  984. write (gol,frmt) 'Initial mass : ',init_mass(region); call goPr
  985. ! write (gol,frmt) 'mass emitted : ',sum_emission(region); call goPr
  986. ! write (gol,frmt) 'chemistry : ',sum_chemistry_all; call goPr
  987. ! write (gol,frmt) 'wet chemistry : ',-sum_wetchem_all; call goPr
  988. write (gol,frmt) 'update_p : ',sum_update_all(region); call goPr
  989. write (gol,frmt) 'advection : ',sum_advection_all(region); call goPr
  990. ! write (gol,frmt) 'deposition : ',sum_deposition(region); call goPr
  991. ! write (gol,frmt) 'stratosphere : ',sum_stratosphere(region); call goPr
  992. write (gol,frmt) 'Final mass : ',mass(region); call goPr
  993. write (gol,frmt) 'Budget (error) : ', &
  994. init_mass(region) +sum_advection_all(region) +sum_update_all(region)-mass(region) ; call goPr
  995. ! write (gol,frmt) 'Budget (error) : ', &
  996. ! init_mass(region) + sum_emission(region) &
  997. ! +sum_advection(region) + sum_chemistry_all &
  998. ! +sum_update(region) &
  999. ! +sum_deposition(region) + sum_stratosphere(region) - sum_wetchem_all - mass; call goPr
  1000. write (gol,'("--------------------------------------------------------")'); call goPr
  1001. end if
  1002. end do
  1003. #ifdef with_hdf4
  1004. if ( isRoot ) then
  1005. call Init(io, budget_file_global, 'write', status)
  1006. IF_NOTOK_RETURN(status=1)
  1007. call WriteAttribute(io, 'initial mass', init_mass, status)
  1008. IF_NOTOK_RETURN(status=1)
  1009. call WriteAttribute(io, 'final mass', mass, status)
  1010. IF_NOTOK_RETURN(status=1)
  1011. call WriteAttribute(io, 'sum_advection', sum_advection_all, status)
  1012. IF_NOTOK_RETURN(status=1)
  1013. call WriteAttribute(io, 'sum_update', sum_update_all, status)
  1014. IF_NOTOK_RETURN(status=1)
  1015. call Done(io,status)
  1016. IF_NOTOK_RETURN(status=1)
  1017. endif
  1018. #endif
  1019. ! ok
  1020. status = 0
  1021. END SUBROUTINE BUDGET_DISPLAYG
  1022. !EOC
  1023. !--------------------------------------------------------------------------
  1024. ! TM5 !
  1025. !--------------------------------------------------------------------------
  1026. !BOP
  1027. !
  1028. ! !IROUTINE: GET_FORMAT
  1029. !
  1030. ! !DESCRIPTION: returns convenient format to write a real
  1031. !\\
  1032. !\\
  1033. ! !INTERFACE:
  1034. !
  1035. SUBROUTINE GET_FORMAT( mm, frmt)
  1036. !
  1037. ! !INPUT PARAMETERS:
  1038. !
  1039. real, intent(in) :: mm
  1040. !
  1041. ! !OUTPUT PARAMETERS:
  1042. !
  1043. character(len=*), intent(out) :: frmt
  1044. !
  1045. !EOP
  1046. !------------------------------------------------------------------------
  1047. !BOC
  1048. integer :: is
  1049. if ( mm > 0.0 ) then
  1050. is = int(alog10(mm))
  1051. else
  1052. is = 0
  1053. end if
  1054. select case(is)
  1055. case(1:10)
  1056. write (frmt,'(a9,i1,a1)') '(a30,f14.', 10-is, ')'
  1057. case default
  1058. frmt = '(a30,1pe12.5)'
  1059. end select
  1060. END SUBROUTINE GET_FORMAT
  1061. !EOC
  1062. END MODULE BUDGET_GLOBAL