sources_sinks.F90 18 KB

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