sources_sinks.F90 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619
  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: SOURCES_SINKS
  13. !
  14. ! !DESCRIPTION: Perform all calculations needed for CBM4 chemistry simulation
  15. ! in TM5: this is mainly emissions, process updates after
  16. ! changes in meteo, boundary, sedimentation, photolysis,...
  17. !
  18. !FD: all emission are converted to kg X (fmw) /month exceptions are mentioned in the code
  19. !
  20. !\\
  21. !\\
  22. ! !INTERFACE:
  23. !
  24. MODULE SOURCES_SINKS
  25. !
  26. ! !USES:
  27. !
  28. use GO, only : gol, goErr, goPr, goBug, goLabel
  29. implicit none
  30. private
  31. !
  32. ! !PUBLIC MEMBER FUNCTIONS:
  33. !
  34. PUBLIC :: SOURCES_SINKS_INIT, SOURCES_SINKS_DONE ! Init and Done methods
  35. PUBLIC :: SS_MONTHLY_UPDATE ! monthly initialization (photolysis,..)
  36. PUBLIC :: SS_AFTER_READ_METEO_UPDATE ! Update SS after met fields are updated. Called from modelIntegration/Proces_update
  37. PUBLIC :: SOURCES_SINKS_APPLY ! apply SS
  38. !
  39. ! !PRIVATE DATA MEMBERS:
  40. !
  41. character(len=*), parameter :: mname = 'sources_sinks'
  42. !
  43. ! !REVISION HISTORY:
  44. ! 19 Mar 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  45. !
  46. ! !REMARKS:
  47. !
  48. !EOP
  49. !------------------------------------------------------------------------------
  50. contains
  51. !------------------------------------------------------------------------------
  52. ! TM5 !
  53. !------------------------------------------------------------------------------
  54. !BOP
  55. !
  56. ! !IROUTINE: SOURCES_SINKS_INIT
  57. !
  58. ! !DESCRIPTION: switch ON required meteo; init emissions
  59. !\\
  60. !\\
  61. ! !INTERFACE:
  62. !
  63. SUBROUTINE SOURCES_SINKS_INIT( status )
  64. !
  65. ! !USES:
  66. !
  67. use meteo, only : Set
  68. use meteodata, only : temper_dat, humid_dat, oro_dat, gph_dat
  69. use Meteodata, only : cp_dat, lsp_dat
  70. use Meteodata, only : cvl_dat, cvh_dat, tv_dat
  71. use Meteodata, only : ci_dat, sd_dat, swvl1_dat
  72. use Meteodata, only : t2m_dat, d2m_dat
  73. use Meteodata, only : lsmask_dat, ci_dat, sst_dat
  74. #if defined(with_online_bvoc) || defined(with_online_nox)
  75. use Meteodata, only : skt_dat
  76. #endif
  77. #ifdef with_online_bvoc
  78. use emission_bvoc_data, only : online_bvoc_skt
  79. #endif
  80. #ifdef with_online_nox
  81. use online_nox_data, only : online_nox_skt
  82. use Meteodata, only : src_dat, lsmask_dat
  83. #endif
  84. use Meteodata, only : ssr_dat, sshf_dat, slhf_dat, ewss_dat, nsss_dat
  85. use Meteodata, only : src_dat, albedo_dat, nveg
  86. use chem_rates, only : rates
  87. #ifndef without_emission
  88. use emission, only : Emission_Init
  89. #endif
  90. #ifndef without_sedimentation
  91. use sedimentation , only : Sedimentation_Init
  92. #endif
  93. #ifndef without_photolysis
  94. use photolysis , only : Photolysis_Init
  95. #endif
  96. #ifndef without_boundary
  97. use boundary , only : Boundary_Init, o3du, use_o3du
  98. #endif
  99. #ifdef with_m7
  100. use emission_dust, only : emission_dust_init
  101. use emission_ss, only : emission_ss_init
  102. #endif
  103. use GO, only : TrcFile, Init, Done, ReadRc
  104. use global_data, only : rcfile
  105. use dims, only : iglbsfc, nregions
  106. !
  107. ! !OUTPUT PARAMETERS:
  108. !
  109. integer, intent(out) :: status
  110. !
  111. ! !REVISION HISTORY:
  112. ! 3 Oct 2012 - P. Le Sager - get Henry coeff (call rates)
  113. !
  114. ! !REMARKS:
  115. !
  116. !EOP
  117. !------------------------------------------------------------------------------
  118. !BOC
  119. integer, parameter :: kr=31 ! standard unit to read auxiliary files
  120. character(len=*), parameter :: rname = mname//'/Sources_Sinks_Init'
  121. type(TrcFile) :: rcF
  122. integer :: region, iveg
  123. ! --- begin ---------------------------------
  124. !--------------------------------------------------
  125. ! ** select meteo (cases not accounted for in the **_init procedures)
  126. !--------------------------------------------------
  127. do region = 1, nregions
  128. #ifndef without_emission
  129. call Set( temper_dat(region), status, used=.true. )
  130. call Set( humid_dat(region), status, used=.true. )
  131. call Set( oro_dat(region), status, used=.true. )
  132. call Set( gph_dat(region), status, used=.true. )
  133. #endif
  134. ! other
  135. call Set( cvl_dat(region), status, used=.true. )
  136. call Set( cvh_dat(region), status, used=.true. )
  137. do iveg=1,nveg
  138. call Set( tv_dat(region,nveg), status, used=.true. )
  139. enddo
  140. call Set( ci_dat(region), status, used=.true. )
  141. call Set( sd_dat(region), status, used=.true. )
  142. call Set( swvl1_dat(region), status, used=.true. )
  143. call Set( t2m_dat(region), status, used=.true. )
  144. call Set( d2m_dat(region), status, used=.true. )
  145. call Set( ssr_dat(region), status, used=.true. )
  146. call Set( sshf_dat(region), status, used=.true. )
  147. call Set( slhf_dat(region), status, used=.true. )
  148. call Set( ewss_dat(region), status, used=.true. )
  149. call Set( nsss_dat(region), status, used=.true. )
  150. call Set( src_dat(region), status, used=.true. )
  151. call Set( albedo_dat(region), status, used=.true. )
  152. enddo
  153. !--------------------------------------------------
  154. ! ** Henry coefficients (must be before sedimentation_init)
  155. !--------------------------------------------------
  156. call rates(status)
  157. IF_NOTOK_RETURN(status=1)
  158. !--------------------------------------------------
  159. ! ** Sedimentation
  160. !--------------------------------------------------
  161. #ifndef without_sedimentation
  162. call Sedimentation_Init( status )
  163. IF_NOTOK_RETURN(status=1)
  164. #endif
  165. !--------------------------------------------------
  166. ! ** Stratospheric boundary (must be before photolysis)
  167. !--------------------------------------------------
  168. #ifndef without_boundary
  169. call Boundary_Init( .true., status )
  170. IF_NOTOK_RETURN(status=1)
  171. #endif
  172. !--------------------------------------------------
  173. ! ** Photolysis
  174. !--------------------------------------------------
  175. #ifndef without_photolysis
  176. #ifdef without_boundary
  177. call photolysis_init(.true., kr )
  178. #else
  179. if (use_o3du) then
  180. call Photolysis_Init(.true., kr, o3du )
  181. else
  182. call Photolysis_Init(.true., kr )
  183. end if
  184. #endif
  185. #endif
  186. !--------------------------------------------------
  187. ! ** Emissions
  188. !--------------------------------------------------
  189. #ifndef without_emission
  190. call Emission_Init( status )
  191. IF_NOTOK_RETURN(status=1)
  192. #ifdef with_online_bvoc
  193. call Init( rcF, rcfile, status )
  194. IF_NOTOK_RETURN(status=1)
  195. call ReadRc( rcF, 'online.bvoc.skt', online_bvoc_skt, status )
  196. IF_NOTOK_RETURN(status=1)
  197. call Done( rcF, status )
  198. IF_NOTOK_RETURN(status=1)
  199. if (online_bvoc_skt) then
  200. call Set( skt_dat(iglbsfc), status, used=.true. )
  201. else
  202. call Set( t2m_dat(iglbsfc), status, used=.true. )
  203. endif
  204. call Set( ssr_dat(iglbsfc), status, used=.true. )
  205. #endif
  206. #ifdef with_online_nox
  207. call Init( rcF, rcfile, status )
  208. IF_NOTOK_RETURN(status=1)
  209. call ReadRc( rcF, 'online.nox.skt', online_nox_skt, status )
  210. IF_NOTOK_RETURN(status=1)
  211. call Done( rcF, status )
  212. IF_NOTOK_RETURN(status=1)
  213. if (online_nox_skt) then
  214. call Set( skt_dat(iglbsfc), status, used=.true. )
  215. else
  216. call Set( t2m_dat(iglbsfc), status, used=.true. )
  217. endif
  218. call Set( lsp_dat(iglbsfc), status, used=.true. )
  219. call Set( cp_dat(iglbsfc), status, used=.true. )
  220. call Set( src_dat(iglbsfc), status, used=.true. )
  221. call Set( lsmask_dat(iglbsfc), status, used=.true. )
  222. #endif
  223. #endif /* EMISSIONS */
  224. #ifdef with_m7
  225. call emission_dust_init( status )
  226. call emission_ss_init( status )
  227. #endif
  228. !--------------------------------------------------
  229. ! ** Done
  230. !--------------------------------------------------
  231. status = 0
  232. END SUBROUTINE SOURCES_SINKS_INIT
  233. !EOC
  234. !------------------------------------------------------------------------------
  235. ! TM5 !
  236. !------------------------------------------------------------------------------
  237. !BOP
  238. !
  239. ! !IROUTINE: SOURCES_SINKS_DONE
  240. !
  241. ! !DESCRIPTION:
  242. !\\
  243. !\\
  244. ! !INTERFACE:
  245. !
  246. SUBROUTINE SOURCES_SINKS_DONE( status )
  247. !
  248. ! !USES:
  249. !
  250. #ifndef without_photolysis
  251. use photolysis, only: photolysis_done
  252. #endif
  253. #ifndef without_sedimentation
  254. use sedimentation, only: Sedimentation_Done
  255. #endif
  256. #ifndef without_boundary
  257. use Boundary, only: Boundary_Done
  258. #endif
  259. #ifndef without_emission
  260. use emission, only: Emission_Done
  261. #endif
  262. !
  263. ! !OUTPUT PARAMETERS:
  264. !
  265. integer, intent(out) :: status
  266. !
  267. ! !REVISION HISTORY:
  268. !
  269. !EOP
  270. !------------------------------------------------------------------------------
  271. !BOC
  272. character(len=*), parameter :: rname = mname//'/Sources_Sinks_Done'
  273. ! --- begin --------------------------------
  274. #ifndef without_photolysis
  275. call photolysis_done ( status )
  276. IF_NOTOK_RETURN(status=1)
  277. #endif
  278. #ifndef without_boundary
  279. call Boundary_Done( status )
  280. IF_NOTOK_RETURN(status=1)
  281. #endif
  282. #ifndef without_sedimentation
  283. call Sedimentation_Done( status )
  284. IF_NOTOK_RETURN(status=1)
  285. #endif
  286. #ifndef without_emission
  287. call Emission_Done( status )
  288. IF_NOTOK_RETURN(status=1)
  289. #endif
  290. status = 0
  291. END SUBROUTINE SOURCES_SINKS_DONE
  292. !EOC
  293. !------------------------------------------------------------------------------
  294. ! TM5 !
  295. !------------------------------------------------------------------------------
  296. !BOP
  297. !
  298. ! !IROUTINE: SS_MONTHLY_UPDATE
  299. !
  300. ! !DESCRIPTION: monthly (re)initialisation of sources/sinks
  301. !\\
  302. !\\
  303. ! !INTERFACE:
  304. !
  305. SUBROUTINE SS_MONTHLY_UPDATE( status )
  306. !
  307. ! !USES:
  308. !
  309. use dims, only : mlen, sec_day, sec_month, sec_year
  310. use datetime, only : calc_sm
  311. #ifndef without_photolysis
  312. use photolysis , only : photolysis_init
  313. #endif
  314. #ifndef without_emission
  315. use emission, only : declare_emission
  316. #endif
  317. #ifndef without_boundary
  318. use boundary, only : Boundary_Init, o3du, use_o3du
  319. #endif
  320. !
  321. ! !OUTPUT PARAMETERS:
  322. !
  323. integer, intent(out) :: status
  324. !
  325. ! !REVISION HISTORY:
  326. ! 19 Mar 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  327. !
  328. ! !REMARKS:
  329. ! (1) routine is called at start and at beginning of each month
  330. !
  331. !EOP
  332. !------------------------------------------------------------------------------
  333. !BOC
  334. character(len=*), parameter :: rname = mname//'/ss_monthly_update'
  335. integer, parameter :: kr=31 ! standard unit to read auxiliary files
  336. ! --- begin ------------------------------------
  337. ! calculate some conversion factors related to time...
  338. call calc_sm( mlen, sec_day, sec_month, sec_year )
  339. ! Read monthly emissions
  340. #ifndef without_emission
  341. call declare_emission( status )
  342. IF_NOTOK_RETURN(status=1)
  343. #endif
  344. ! Monthly update for stratospheric boundary
  345. #ifndef without_boundary
  346. call Boundary_Init( .false., status )
  347. IF_NOTOK_RETURN(status=1)
  348. #endif
  349. ! Monthly update for photolysis
  350. #ifndef without_photolysis
  351. #ifndef without_boundary
  352. if (use_o3du) then
  353. call Photolysis_Init( .false., kr, o3du )
  354. end if
  355. #endif
  356. #endif
  357. status = 0
  358. END SUBROUTINE SS_MONTHLY_UPDATE
  359. !EOC
  360. !------------------------------------------------------------------------------
  361. ! TM5 !
  362. !------------------------------------------------------------------------------
  363. !BOP
  364. !
  365. ! !IROUTINE: SS_AFTER_READ_METEO_UPDATE
  366. !
  367. ! !DESCRIPTION: subroutine that is called after reading new met fields (clouds,
  368. ! surface winds, etc.).
  369. ! In this routine, 'chemistry' fields that depend on these
  370. ! data are calculated. Called from modelIntegration/Proces_update.
  371. !\\
  372. !\\
  373. ! !INTERFACE:
  374. !
  375. SUBROUTINE SS_AFTER_READ_METEO_UPDATE( status )
  376. !
  377. ! !USES:
  378. !
  379. use dims, only : nregions, sec_month
  380. use tm5_distgrid, only : dgrid, Get_DistGrid
  381. #ifndef without_photolysis
  382. use photolysis, only : ozone_info_online, slingo, aerosol_info, update_csqy
  383. #endif
  384. #ifndef without_emission
  385. use emission_nox, only : eminox_lightning
  386. #ifndef without_convection
  387. use emission_nox, only : lightningNOX
  388. #endif
  389. use emission_dms, only : getDMS
  390. #if defined(with_online_bvoc) || defined(with_online_nox)
  391. use dims, only : itau, ndyn_max
  392. #endif
  393. #ifdef with_online_bvoc
  394. use emission_bvoc, only : getBVOC
  395. #endif
  396. #ifdef with_online_nox
  397. use online_nox, only : getNOx
  398. use emission_nox, only : nat_nox
  399. #endif
  400. #ifdef with_m7
  401. use emission_dust, only : calc_emission_dust, read_emission_dust
  402. use emission_ss, only : calc_emission_ss
  403. #endif
  404. #endif /* EMISSIONS */
  405. #ifndef without_sedimentation
  406. use sedimentation, only : calculate_rh
  407. #endif
  408. !
  409. ! !OUTPUT PARAMETERS:
  410. !
  411. integer, intent(out) :: status
  412. !
  413. ! !REVISION HISTORY:
  414. ! 19 Mar 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  415. !
  416. ! !REMARKS:
  417. !
  418. !EOP
  419. !------------------------------------------------------------------------------
  420. !BOC
  421. character(len=*), parameter :: rname = 'ss_after_read_meteo_update'
  422. integer :: region, i1, j1
  423. ! --- begin ------------------------------------
  424. call goLabel()
  425. #ifndef without_emission
  426. #ifdef with_online_nox
  427. if (mod(itau, ndyn_max) == 0) then
  428. call getNOx(status) ! returns nat_nox in kg(N)/month
  429. IF_NOTOK_RETURN(status=1)
  430. endif
  431. #endif
  432. !get dms_emissions dms_sea, flagged by new_surface meteo fields get in kgS/month
  433. call getDMS( status )
  434. IF_NOTOK_RETURN(status=1)
  435. #ifdef with_online_bvoc
  436. if (mod(itau, ndyn_max) == 0) then
  437. ! TvN: added fixed time step ndyn_max (1 hour)
  438. ! because the averages over the past 24 hours are calculated from hourly averages
  439. call getBVOC (status)
  440. IF_NOTOK_RETURN(status=1)
  441. endif
  442. #endif
  443. ! Lightning NOx (defined only if convection is turned on)
  444. #ifdef without_convection
  445. do region = 1, nregions
  446. eminox_lightning(region)%d3=0.
  447. end do
  448. #else
  449. do region = 1, nregions
  450. call Get_DistGrid( dgrid(region), I_STRT=i1, J_STRT=j1 )
  451. call lightningNOX(region, i1, j1, eminox_lightning(region)%d3, status)
  452. IF_NOTOK_RETURN(status=1)
  453. eminox_lightning(region)%d3(:,:,:) = eminox_lightning(region)%d3(:,:,:)*sec_month !from kg N/s ----> kg N/month
  454. end do
  455. #endif
  456. #ifdef with_m7
  457. call calc_emission_ss( status )
  458. IF_NOTOK_RETURN(status=1)
  459. call read_emission_dust( status ) ! this is active if (input.emis.dust /= ONLINE)
  460. IF_NOTOK_RETURN(status=1)
  461. call calc_emission_dust( status ) ! this is active if (input.emis.dust == ONLINE)
  462. IF_NOTOK_RETURN(status=1)
  463. #endif
  464. #endif /* EMISSIONS */
  465. #ifndef without_photolysis
  466. do region = 1, nregions
  467. ! cloud optical depth
  468. call slingo(region)
  469. ! calculate optical depth ozone from current ozone field
  470. ! note: this routine does not depend on clouds but on rm ...
  471. call ozone_info_online(region)
  472. call update_csqy( region ) ! t/p-dependent cross-sections and quantum yields
  473. end do
  474. #endif
  475. #ifndef without_sedimentation
  476. call calculate_rh
  477. #endif
  478. ! ok
  479. call goLabel()
  480. status = 0
  481. END SUBROUTINE SS_AFTER_READ_METEO_UPDATE
  482. !EOC
  483. !------------------------------------------------------------------------------
  484. ! TM5 !
  485. !------------------------------------------------------------------------------
  486. !BOP
  487. !
  488. ! !IROUTINE: SOURCES_SINKS_APPLY
  489. !
  490. ! !DESCRIPTION: this subroutine changes the tracer mass and its
  491. ! slopes by chemical sources.
  492. !\\
  493. !\\
  494. ! !INTERFACE:
  495. !
  496. SUBROUTINE SOURCES_SINKS_APPLY( region, tr, status )
  497. !
  498. ! !USES:
  499. !
  500. use GO, only : TDate
  501. #ifndef without_emission
  502. use emission, only: emission_apply
  503. #endif
  504. #ifndef without_sedimentation
  505. use sedimentation, only: Sedimentation_Apply
  506. #endif
  507. #ifndef without_boundary
  508. use boundary, only : Boundary_Apply
  509. #endif
  510. !
  511. ! !INPUT PARAMETERS:
  512. !
  513. integer, intent(in) :: region
  514. type(TDate) :: tr(2)
  515. !
  516. ! !OUTPUT PARAMETERS:
  517. !
  518. integer, intent(out) :: status
  519. !
  520. ! !REVISION HISTORY:
  521. !
  522. ! !REMARKS:
  523. ! - called each time step, during "source" step, by modelIntegration/do_steps
  524. !
  525. !EOP
  526. !------------------------------------------------------------------------------
  527. !BOC
  528. character(len=*), parameter :: rname = mname//'/Sources_sinks_apply'
  529. ! --- begin ----------------------------------
  530. #ifndef without_sedimentation
  531. call Sedimentation_Apply ( region, status )
  532. IF_NOTOK_RETURN(status=1)
  533. #endif
  534. #ifndef without_emission
  535. ! note dust/ss emissions are ported to sedimentation routine
  536. call emission_apply( region, status )
  537. IF_NOTOK_RETURN(status=1)
  538. #endif
  539. ! Apply boundary conditions to selected tracers
  540. #ifndef without_chemistry
  541. #ifndef without_boundary
  542. call Boundary_Apply( region, status )
  543. IF_NOTOK_RETURN(status=1)
  544. #endif
  545. #endif
  546. status = 0
  547. END SUBROUTINE SOURCES_SINKS_APPLY
  548. !EOC
  549. END MODULE SOURCES_SINKS