sources_sinks.F90 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  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 : u10m_dat, v10m_dat, lsmask_dat,ci_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 : u10m_dat, v10m_dat, 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( u10m_dat(region), status, used=.true. )
  151. call Set( v10m_dat(region), status, used=.true. )
  152. call Set( src_dat(region), status, used=.true. )
  153. call Set( albedo_dat(region), status, used=.true. )
  154. enddo
  155. ! special set for DMS
  156. call Set( t2m_dat(iglbsfc), status, used=.true. )
  157. call Set( u10m_dat(iglbsfc), status, used=.true. )
  158. call Set( v10m_dat(iglbsfc), status, used=.true. )
  159. !--------------------------------------------------
  160. ! ** Henry coefficients (must be before sedimentation_init)
  161. !--------------------------------------------------
  162. call rates(status)
  163. IF_NOTOK_RETURN(status=1)
  164. !--------------------------------------------------
  165. ! ** Sedimentation
  166. !--------------------------------------------------
  167. #ifndef without_sedimentation
  168. call Sedimentation_Init( status )
  169. IF_NOTOK_RETURN(status=1)
  170. #endif
  171. !--------------------------------------------------
  172. ! ** Stratospheric boundary (must be before photolysis)
  173. !--------------------------------------------------
  174. #ifndef without_boundary
  175. call Boundary_Init( .true., status )
  176. IF_NOTOK_RETURN(status=1)
  177. #endif
  178. !--------------------------------------------------
  179. ! ** Photolysis
  180. !--------------------------------------------------
  181. #ifndef without_photolysis
  182. #ifdef without_boundary
  183. call photolysis_init(.true., kr )
  184. #else
  185. if (use_o3du) then
  186. call Photolysis_Init(.true., kr, o3du )
  187. else
  188. call Photolysis_Init(.true., kr )
  189. end if
  190. #endif
  191. #endif
  192. !--------------------------------------------------
  193. ! ** Emissions
  194. !--------------------------------------------------
  195. #ifndef without_emission
  196. call Emission_Init( status )
  197. IF_NOTOK_RETURN(status=1)
  198. #ifdef with_online_bvoc
  199. call Init( rcF, rcfile, status )
  200. IF_NOTOK_RETURN(status=1)
  201. call ReadRc( rcF, 'online.bvoc.skt', online_bvoc_skt, status )
  202. IF_NOTOK_RETURN(status=1)
  203. call Done( rcF, status )
  204. IF_NOTOK_RETURN(status=1)
  205. if (online_bvoc_skt) then
  206. call Set( skt_dat(iglbsfc), status, used=.true. )
  207. else
  208. call Set( t2m_dat(iglbsfc), status, used=.true. )
  209. endif
  210. call Set( ssr_dat(iglbsfc), status, used=.true. )
  211. #endif
  212. #ifdef with_online_nox
  213. call Init( rcF, rcfile, status )
  214. IF_NOTOK_RETURN(status=1)
  215. call ReadRc( rcF, 'online.nox.skt', online_nox_skt, status )
  216. IF_NOTOK_RETURN(status=1)
  217. call Done( rcF, status )
  218. IF_NOTOK_RETURN(status=1)
  219. if (online_nox_skt) then
  220. call Set( skt_dat(iglbsfc), status, used=.true. )
  221. else
  222. call Set( t2m_dat(iglbsfc), status, used=.true. )
  223. endif
  224. call Set( lsp_dat(iglbsfc), status, used=.true. )
  225. call Set( cp_dat(iglbsfc), status, used=.true. )
  226. call Set( src_dat(iglbsfc), status, used=.true. )
  227. call Set( lsmask_dat(iglbsfc), status, used=.true. )
  228. #endif
  229. #endif /* EMISSIONS */
  230. #ifdef with_m7
  231. call emission_dust_init( status )
  232. call emission_ss_init( status )
  233. #endif
  234. !--------------------------------------------------
  235. ! ** Done
  236. !--------------------------------------------------
  237. status = 0
  238. END SUBROUTINE SOURCES_SINKS_INIT
  239. !EOC
  240. !------------------------------------------------------------------------------
  241. ! TM5 !
  242. !------------------------------------------------------------------------------
  243. !BOP
  244. !
  245. ! !IROUTINE: SOURCES_SINKS_DONE
  246. !
  247. ! !DESCRIPTION:
  248. !\\
  249. !\\
  250. ! !INTERFACE:
  251. !
  252. SUBROUTINE SOURCES_SINKS_DONE( status )
  253. !
  254. ! !USES:
  255. !
  256. #ifndef without_photolysis
  257. use photolysis, only: photolysis_done
  258. #endif
  259. #ifndef without_sedimentation
  260. use sedimentation, only: Sedimentation_Done
  261. #endif
  262. #ifndef without_boundary
  263. use Boundary, only: Boundary_Done
  264. #endif
  265. #ifndef without_emission
  266. use emission, only: Emission_Done
  267. #endif
  268. !
  269. ! !OUTPUT PARAMETERS:
  270. !
  271. integer, intent(out) :: status
  272. !
  273. ! !REVISION HISTORY:
  274. !
  275. !EOP
  276. !------------------------------------------------------------------------------
  277. !BOC
  278. character(len=*), parameter :: rname = mname//'/Sources_Sinks_Done'
  279. ! --- begin --------------------------------
  280. #ifndef without_photolysis
  281. call photolysis_done ( status )
  282. IF_NOTOK_RETURN(status=1)
  283. #endif
  284. #ifndef without_boundary
  285. call Boundary_Done( status )
  286. IF_NOTOK_RETURN(status=1)
  287. #endif
  288. #ifndef without_sedimentation
  289. call Sedimentation_Done( status )
  290. IF_NOTOK_RETURN(status=1)
  291. #endif
  292. #ifndef without_emission
  293. call Emission_Done( status )
  294. IF_NOTOK_RETURN(status=1)
  295. #endif
  296. status = 0
  297. END SUBROUTINE SOURCES_SINKS_DONE
  298. !EOC
  299. !------------------------------------------------------------------------------
  300. ! TM5 !
  301. !------------------------------------------------------------------------------
  302. !BOP
  303. !
  304. ! !IROUTINE: SS_MONTHLY_UPDATE
  305. !
  306. ! !DESCRIPTION: monthly (re)initialisation of sources/sinks
  307. !\\
  308. !\\
  309. ! !INTERFACE:
  310. !
  311. SUBROUTINE SS_MONTHLY_UPDATE( status )
  312. !
  313. ! !USES:
  314. !
  315. use dims, only : mlen, sec_day, sec_month, sec_year
  316. use datetime, only : calc_sm
  317. #ifndef without_photolysis
  318. use photolysis , only : photolysis_init
  319. #endif
  320. #ifndef without_emission
  321. use emission, only : declare_emission
  322. #endif
  323. #ifndef without_boundary
  324. use boundary, only : Boundary_Init, o3du, use_o3du
  325. #endif
  326. !
  327. ! !OUTPUT PARAMETERS:
  328. !
  329. integer, intent(out) :: status
  330. !
  331. ! !REVISION HISTORY:
  332. ! 19 Mar 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  333. !
  334. ! !REMARKS:
  335. ! (1) routine is called at the beginning of every month
  336. !
  337. !EOP
  338. !------------------------------------------------------------------------------
  339. !BOC
  340. character(len=*), parameter :: rname = mname//'/ss_monthly_update'
  341. integer, parameter :: kr=31 ! standard unit to read auxiliary files
  342. ! --- begin ------------------------------------
  343. ! calculate some conversion factors related to time...
  344. call calc_sm( mlen, sec_day, sec_month, sec_year )
  345. ! Read monthly emissions
  346. #ifndef without_emission
  347. call declare_emission( status )
  348. IF_NOTOK_RETURN(status=1)
  349. #endif
  350. ! Monthly update for stratospheric boundary
  351. #ifndef without_boundary
  352. call Boundary_Init( .false., status )
  353. IF_NOTOK_RETURN(status=1)
  354. #endif
  355. ! Monthly update for photolysis
  356. #ifndef without_photolysis
  357. #ifndef without_boundary
  358. if (use_o3du) then
  359. call Photolysis_Init( .false., kr, o3du )
  360. end if
  361. #endif
  362. #endif
  363. status = 0
  364. END SUBROUTINE SS_MONTHLY_UPDATE
  365. !EOC
  366. !------------------------------------------------------------------------------
  367. ! TM5 !
  368. !------------------------------------------------------------------------------
  369. !BOP
  370. !
  371. ! !IROUTINE: SS_AFTER_READ_METEO_UPDATE
  372. !
  373. ! !DESCRIPTION: subroutine that is called after reading new met fields (clouds,
  374. ! surface winds, etc.).
  375. ! In this routine, 'chemistry' fields that depend on these
  376. ! data are calculated. Called from modelIntegration/Proces_update.
  377. !\\
  378. !\\
  379. ! !INTERFACE:
  380. !
  381. SUBROUTINE SS_AFTER_READ_METEO_UPDATE( status )
  382. !
  383. ! !USES:
  384. !
  385. use dims, only : nregions, sec_month
  386. use tm5_distgrid, only : dgrid, Get_DistGrid
  387. #ifndef without_photolysis
  388. use photolysis, only : ozone_info_online, slingo, aerosol_info, update_csqy
  389. #endif
  390. #ifndef without_emission
  391. use emission_nox, only : eminox_lightning
  392. #ifndef without_convection
  393. use emission_nox, only : lightningNOX
  394. #endif
  395. use emission_dms, only : getDMS
  396. #if defined(with_online_bvoc) || defined(with_online_nox)
  397. use dims, only : itau, ndyn_max
  398. #endif
  399. #ifdef with_online_bvoc
  400. use emission_bvoc, only : getBVOC
  401. #endif
  402. #ifdef with_online_nox
  403. use online_nox, only : getNOx
  404. use emission_nox, only : nat_nox
  405. #endif
  406. #ifdef with_m7
  407. use emission_dust, only : calc_emission_dust, read_emission_dust
  408. use emission_ss, only : calc_emission_ss
  409. #endif
  410. #endif /* EMISSIONS */
  411. #ifndef without_sedimentation
  412. use sedimentation, only : calculate_rh
  413. #endif
  414. !
  415. ! !OUTPUT PARAMETERS:
  416. !
  417. integer, intent(out) :: status
  418. !
  419. ! !REVISION HISTORY:
  420. ! 19 Mar 2012 - P. Le Sager - adapted for lon-lat MPI domain decomposition
  421. !
  422. ! !REMARKS:
  423. !
  424. !EOP
  425. !------------------------------------------------------------------------------
  426. !BOC
  427. character(len=*), parameter :: rname = 'ss_after_read_meteo_update'
  428. integer :: region, i1, j1
  429. ! --- begin ------------------------------------
  430. call goLabel()
  431. #ifndef without_emission
  432. #ifdef with_online_nox
  433. if (mod(itau, ndyn_max) == 0) then
  434. call getNOx(status) ! returns nat_nox in kg(N)/month
  435. IF_NOTOK_RETURN(status=1)
  436. endif
  437. #endif
  438. !get dms_emissions dms_sea, flagged by new_surface meteo fields get in kgS/month
  439. call getDMS( status )
  440. IF_NOTOK_RETURN(status=1)
  441. #ifdef with_online_bvoc
  442. if (mod(itau, ndyn_max) == 0) then
  443. ! TvN: added fixed time step ndyn_max (1 hour)
  444. ! because the averages over the past 24 hours are calculated from hourly averages
  445. call getBVOC (status)
  446. IF_NOTOK_RETURN(status=1)
  447. endif
  448. #endif
  449. ! Lightning NOx (defined only if convection is turned on)
  450. #ifdef without_convection
  451. do region = 1, nregions
  452. eminox_lightning(region)%d3=0.
  453. end do
  454. #else
  455. do region = 1, nregions
  456. call Get_DistGrid( dgrid(region), I_STRT=i1, J_STRT=j1 )
  457. call lightningNOX(region, i1, j1, eminox_lightning(region)%d3, status)
  458. IF_NOTOK_RETURN(status=1)
  459. eminox_lightning(region)%d3(:,:,:) = eminox_lightning(region)%d3(:,:,:)*sec_month !from kg N/s ----> kg N/month
  460. end do
  461. #endif
  462. #ifdef with_m7
  463. call calc_emission_ss( status )
  464. IF_NOTOK_RETURN(status=1)
  465. call read_emission_dust( status ) ! this is active if (input.emis.dust /= ONLINE)
  466. IF_NOTOK_RETURN(status=1)
  467. call calc_emission_dust( status ) ! this is active if (input.emis.dust == ONLINE)
  468. IF_NOTOK_RETURN(status=1)
  469. #endif
  470. #endif /* EMISSIONS */
  471. #ifndef without_photolysis
  472. do region = 1, nregions
  473. ! cloud optical depth
  474. call slingo(region)
  475. ! calculate optical depth ozone from current ozone field
  476. ! note: this routine does not depend on clouds but on rm ...
  477. call ozone_info_online(region)
  478. call update_csqy( region ) ! t/p-dependent cross-sections and quantum yields
  479. end do
  480. #endif
  481. #ifndef without_sedimentation
  482. call calculate_rh
  483. #endif
  484. ! ok
  485. call goLabel()
  486. status = 0
  487. END SUBROUTINE SS_AFTER_READ_METEO_UPDATE
  488. !EOC
  489. !------------------------------------------------------------------------------
  490. ! TM5 !
  491. !------------------------------------------------------------------------------
  492. !BOP
  493. !
  494. ! !IROUTINE: SOURCES_SINKS_APPLY
  495. !
  496. ! !DESCRIPTION: this subroutine changes the tracer mass and its
  497. ! slopes by chemical sources.
  498. !\\
  499. !\\
  500. ! !INTERFACE:
  501. !
  502. SUBROUTINE SOURCES_SINKS_APPLY( region, tr, status )
  503. !
  504. ! !USES:
  505. !
  506. use GO, only : TDate
  507. #ifndef without_emission
  508. use emission, only: emission_apply
  509. #endif
  510. #ifndef without_sedimentation
  511. use sedimentation, only: Sedimentation_Apply
  512. #endif
  513. #ifndef without_boundary
  514. use boundary, only : Boundary_Apply
  515. #endif
  516. !
  517. ! !INPUT PARAMETERS:
  518. !
  519. integer, intent(in) :: region
  520. type(TDate) :: tr(2)
  521. !
  522. ! !OUTPUT PARAMETERS:
  523. !
  524. integer, intent(out) :: status
  525. !
  526. ! !REVISION HISTORY:
  527. !
  528. ! !REMARKS:
  529. ! - called each time step, during "source" step, by modelIntegration/do_steps
  530. !
  531. !EOP
  532. !------------------------------------------------------------------------------
  533. !BOC
  534. character(len=*), parameter :: rname = mname//'/Sources_sinks_apply'
  535. ! --- begin ----------------------------------
  536. #ifndef without_sedimentation
  537. call Sedimentation_Apply ( region, status )
  538. IF_NOTOK_RETURN(status=1)
  539. #endif
  540. #ifndef without_emission
  541. ! note dust/ss emissions are ported to sedimentation routine
  542. call emission_apply( region, status )
  543. IF_NOTOK_RETURN(status=1)
  544. #endif
  545. ! Apply boundary conditions to selected tracers
  546. #ifndef without_chemistry
  547. #ifndef without_boundary
  548. call Boundary_Apply( region, status )
  549. IF_NOTOK_RETURN(status=1)
  550. #endif
  551. #endif
  552. status = 0
  553. END SUBROUTINE SOURCES_SINKS_APPLY
  554. !EOC
  555. END MODULE SOURCES_SINKS