PageRenderTime 60ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/wrfv2_fire/phys/module_fr_sfire_atm.F

http://github.com/jbeezley/wrf-fire
FORTRAN Legacy | 2218 lines | 1267 code | 333 blank | 618 comment | 61 complexity | 01cc9230d1f3bc6663e5572fcf894d4f MD5 | raw file
Possible License(s): AGPL-1.0

Large files files are truncated, but you can click here to view the full file

  1. !WRF:MEDIATION_LAYER:FIRE_MODEL
  2. !*** Jan Mandel August 2007 - February 2010
  3. !*** email: Jan.Mandel@gmail.com
  4. ! Routines dealing with the atmosphere
  5. module module_fr_sfire_atm
  6. use module_model_constants, only: cp,xlv,g
  7. use module_fr_sfire_phys, only: fire_wind_height,have_fuel_cats,fcz0,fcwh,nfuelcats,no_fuel_cat,no_fuel_cat2,windrf
  8. use module_fr_sfire_util
  9. USE module_dm , only : wrf_dm_sum_reals
  10. use module_fr_sfire_phys, only: mfuelcats, nfuelcats ! for emissions
  11. USE module_state_description, only: num_tracer
  12. use module_fr_sfire_phys, only: fuel_name
  13. #ifdef WRF_CHEM
  14. USE module_state_description, only: num_chem
  15. USE module_configure, only: &
  16. p_co, &
  17. p_ch4, &
  18. p_h2, &
  19. p_no, &
  20. p_no2, &
  21. p_so2, &
  22. p_nh3, &
  23. p_p25, &
  24. p_p25i, &
  25. p_p25j, &
  26. p_oc1, &
  27. p_oc2, &
  28. p_bc1, &
  29. p_bc2, &
  30. p_ald, &
  31. p_csl, &
  32. p_eth, &
  33. p_hc3, &
  34. p_hc5, &
  35. p_hcho, &
  36. p_iso, &
  37. p_ket, &
  38. p_mgly, &
  39. p_ol2, &
  40. p_olt, &
  41. p_oli, &
  42. p_ora2,&
  43. p_tol, &
  44. p_xyl, &
  45. p_bigalk, &
  46. p_bigene, &
  47. p_c10h16, &
  48. p_c2h4, &
  49. p_c2h5oh, &
  50. p_c2h6, &
  51. p_c3h6, &
  52. p_c3h8, &
  53. p_ch3cooh, &
  54. p_ch3oh, &
  55. p_cres, &
  56. p_glyald, &
  57. ! p_hyac, &
  58. p_isopr, &
  59. p_macr, &
  60. p_mek, &
  61. p_mvk, &
  62. p_smoke ! tracer smoke exists only with CHEM
  63. #endif
  64. USE module_state_description, only: &
  65. p_tr17_1, &
  66. p_tr17_2, &
  67. p_tr17_3, &
  68. p_tr17_4, &
  69. p_tr17_5, &
  70. p_tr17_6, &
  71. p_tr17_7, &
  72. p_tr17_8
  73. implicit none
  74. #ifndef WRF_CHEM
  75. integer, parameter, private:: num_chem=0
  76. #endif
  77. logical, save :: have_wind_log_interpolation = .false. ! status
  78. ! emission tables
  79. REAL, dimension(mfuelcats), save:: &
  80. co=0., &
  81. ch4=0., &
  82. h2=0., &
  83. no=0., &
  84. no2=0., &
  85. so2=0., &
  86. nh3=0., &
  87. oc1=0., &
  88. oc2=0., &
  89. bc1=0., &
  90. bc2=0., &
  91. ald=0., &
  92. csl=0., &
  93. eth=0., &
  94. hc3=0., &
  95. p25=0., &
  96. p25i=0., &
  97. p25j=0., &
  98. hc5=0., &
  99. hcho=0., &
  100. iso=0., &
  101. ket=0., &
  102. mgly=0., &
  103. ol2=0., &
  104. olt=0., &
  105. oli=0., &
  106. ora2=0.,&
  107. tol=0., &
  108. xyl=0., &
  109. bigalk=0., &
  110. bigene=0., &
  111. c10h16=0., &
  112. c2h4=0., &
  113. c2h5oh=0., &
  114. c2h6=0., &
  115. c3h6=0., &
  116. c3h8=0., &
  117. ch3cooh=0., &
  118. ch3oh=0., &
  119. cres=0., &
  120. glyald=0., &
  121. ! hyac=0., &
  122. isopr=0., &
  123. macr=0., &
  124. mek=0., &
  125. mvk=0., &
  126. smoke=0., &
  127. tr17_1=0., &
  128. tr17_2=0., &
  129. tr17_3=0., &
  130. tr17_4=0., &
  131. tr17_5=0., &
  132. tr17_6=0., &
  133. tr17_7=0., &
  134. tr17_8=0.
  135. real, parameter:: & ! reciprocal molecular weights (mol/g)
  136. imw_co = 1./28.010,&
  137. imw_ch4 = 1./16.04,&
  138. imw_h2 = 1./2.016,&
  139. imw_no = 1./30.006,&
  140. imw_no2 = 1./46.006,&
  141. imw_so2 = 1./64.066,&
  142. imw_nh3 = 1./17.031
  143. real, parameter:: mw_air=28.97 ! molecular weight of air g/mol
  144. ! should be declared in the registry and stored in the state in future because of restarts
  145. real, pointer, save, dimension(:)::c_chem
  146. real, pointer, save, dimension(:)::c_fuel
  147. real, pointer, save, dimension(:)::c_tracer
  148. logical, save:: emis_read = .false.
  149. integer, save:: msglevel =1,printsums=0 ! when to print sums
  150. integer, parameter:: line=5 ! number of species, emissions, etc. per line
  151. contains
  152. ! chem arrays are chem tracer
  153. ! indices p_species are generated in inc/scalar_indices.inc and included in frame/module_configure.F
  154. subroutine read_emissions_table(chem_opt,tracer_opt)
  155. implicit none
  156. integer, intent(in)::chem_opt,tracer_opt
  157. logical, external:: wrf_dm_on_monitor
  158. external::wrf_dm_bcast_integer , wrf_dm_bcast_real
  159. integer, dimension(10)::compatible_chem_opt
  160. integer:: iounit,ierr,i
  161. character(len=128)::msg
  162. namelist/emissions/ compatible_chem_opt, printsums, &
  163. co, &
  164. ch4, &
  165. h2, &
  166. no, &
  167. no2, &
  168. so2, &
  169. nh3, &
  170. p25, &
  171. p25i, &
  172. p25j, &
  173. oc1, &
  174. oc2, &
  175. bc1, &
  176. bc2, &
  177. ald, &
  178. csl, &
  179. eth, &
  180. hc3, &
  181. hc5, &
  182. hcho, &
  183. iso, &
  184. ket, &
  185. mgly, &
  186. ol2, &
  187. olt, &
  188. oli, &
  189. ora2,&
  190. tol, &
  191. xyl, &
  192. bigalk, &
  193. bigene, &
  194. c10h16, &
  195. c2h4, &
  196. c2h5oh, &
  197. c2h6, &
  198. c3h6, &
  199. c3h8, &
  200. ch3cooh, &
  201. ch3oh, &
  202. cres, &
  203. glyald, &
  204. ! hyac, &
  205. isopr, &
  206. macr, &
  207. mek, &
  208. mvk, &
  209. smoke, &
  210. tr17_1, &
  211. tr17_2, &
  212. tr17_3, &
  213. tr17_4, &
  214. tr17_5, &
  215. tr17_6, &
  216. tr17_7, &
  217. tr17_8
  218. !$ if (OMP_GET_THREAD_NUM() .ne. 0)then
  219. !$ call crash('read_emissions_table: must be called from master thread')
  220. !$ endif
  221. IF ( wrf_dm_on_monitor() ) THEN
  222. ! we are the master task
  223. iounit=open_text_file('namelist.fire_emissions','read')
  224. compatible_chem_opt=0
  225. read(iounit,emissions,iostat=ierr)
  226. if(ierr.ne.0)call crash('read_emissions_table: error reading namelist emissions in file namelist.fire_emissions')
  227. CLOSE(iounit)
  228. write(msg,'(a,i3,a)')'reading emissions table for',nfuelcats,' fuel categories'
  229. call message(msg,level=0)
  230. if (.not.any(compatible_chem_opt.eq.chem_opt))then
  231. write(msg,'(a,i4,a)')'read_emissions_table: chem_opt=',chem_opt,' not between given compatible_chem_opt in namelist.fire_emissions'
  232. call message(msg,level=0)
  233. write(msg,'(a,10i4)')'compatible_chem_opt=', compatible_chem_opt
  234. call message(msg,level=0)
  235. call crash('chem_opt in namelist.input is not consistent with namelist.fire_emissions')
  236. endif
  237. ENDIF
  238. call wrf_dm_bcast_integer(printsums, 1)
  239. call wrf_dm_bcast_real(co, nfuelcats)
  240. call wrf_dm_bcast_real(ch4, nfuelcats)
  241. call wrf_dm_bcast_real(h2, nfuelcats)
  242. call wrf_dm_bcast_real(no, nfuelcats)
  243. call wrf_dm_bcast_real(no2, nfuelcats)
  244. call wrf_dm_bcast_real(so2, nfuelcats)
  245. call wrf_dm_bcast_real(nh3, nfuelcats)
  246. call wrf_dm_bcast_real(p25, nfuelcats)
  247. call wrf_dm_bcast_real(p25i, nfuelcats)
  248. call wrf_dm_bcast_real(p25j, nfuelcats)
  249. call wrf_dm_bcast_real(oc1, nfuelcats)
  250. call wrf_dm_bcast_real(oc2, nfuelcats)
  251. call wrf_dm_bcast_real(bc1, nfuelcats)
  252. call wrf_dm_bcast_real(bc2, nfuelcats)
  253. call wrf_dm_bcast_real(ald, nfuelcats)
  254. call wrf_dm_bcast_real(csl, nfuelcats)
  255. call wrf_dm_bcast_real(eth, nfuelcats)
  256. call wrf_dm_bcast_real(hc3, nfuelcats)
  257. call wrf_dm_bcast_real(hc5, nfuelcats)
  258. call wrf_dm_bcast_real(hcho, nfuelcats)
  259. call wrf_dm_bcast_real(iso, nfuelcats)
  260. call wrf_dm_bcast_real(ket, nfuelcats)
  261. call wrf_dm_bcast_real(mgly, nfuelcats)
  262. call wrf_dm_bcast_real(ol2, nfuelcats)
  263. call wrf_dm_bcast_real(olt, nfuelcats)
  264. call wrf_dm_bcast_real(oli, nfuelcats)
  265. call wrf_dm_bcast_real(ora2,nfuelcats)
  266. call wrf_dm_bcast_real(tol, nfuelcats)
  267. call wrf_dm_bcast_real(xyl, nfuelcats)
  268. call wrf_dm_bcast_real(bigalk, nfuelcats)
  269. call wrf_dm_bcast_real(bigene, nfuelcats)
  270. call wrf_dm_bcast_real(c10h16, nfuelcats)
  271. call wrf_dm_bcast_real(c2h4, nfuelcats)
  272. call wrf_dm_bcast_real(c2h5oh, nfuelcats)
  273. call wrf_dm_bcast_real(c2h6, nfuelcats)
  274. call wrf_dm_bcast_real(c3h6, nfuelcats)
  275. call wrf_dm_bcast_real(c3h8, nfuelcats)
  276. call wrf_dm_bcast_real(ch3cooh, nfuelcats)
  277. call wrf_dm_bcast_real(ch3oh, nfuelcats)
  278. call wrf_dm_bcast_real(cres, nfuelcats)
  279. call wrf_dm_bcast_real(glyald, nfuelcats)
  280. ! call wrf_dm_bcast_real(hyac, nfuelcats)
  281. call wrf_dm_bcast_real(isopr, nfuelcats)
  282. call wrf_dm_bcast_real(macr, nfuelcats)
  283. call wrf_dm_bcast_real(mek, nfuelcats)
  284. call wrf_dm_bcast_real(mvk, nfuelcats)
  285. call wrf_dm_bcast_real(smoke, nfuelcats)
  286. call wrf_dm_bcast_real(tr17_1, nfuelcats)
  287. call wrf_dm_bcast_real(tr17_2, nfuelcats)
  288. call wrf_dm_bcast_real(tr17_3, nfuelcats)
  289. call wrf_dm_bcast_real(tr17_4, nfuelcats)
  290. call wrf_dm_bcast_real(tr17_5, nfuelcats)
  291. call wrf_dm_bcast_real(tr17_6, nfuelcats)
  292. call wrf_dm_bcast_real(tr17_7, nfuelcats)
  293. call wrf_dm_bcast_real(tr17_8, nfuelcats)
  294. if(fire_print_msg .ge. msglevel .and.printsums .gt. 0)then
  295. ! should be stored in the registry future because of restarts
  296. write(msg,'(3(a,i3,1x))')'allocating c_chem size',num_chem,'c_tracer size',num_tracer,'c_fuel size',nfuelcats
  297. call message(msg,level=2)
  298. if(num_chem>0)then
  299. allocate(c_chem(num_chem))
  300. c_chem=0. ! cumulative burnt
  301. endif
  302. if(num_tracer>0)then
  303. allocate(c_tracer(num_tracer))
  304. c_tracer=0. ! cumulative burnt
  305. endif
  306. allocate(c_fuel(nfuelcats))
  307. c_fuel=0. ! total per timestep, rate burnt, cumulative burnt
  308. write(msg,'(a,i3,a,i3)')'allocated c_chem size',size(c_chem),' c_fuel size',size(c_fuel)
  309. call message(msg,level=2)
  310. endif
  311. emis_read=.true.
  312. end subroutine read_emissions_table
  313. subroutine add_fire_emissions(chem_opt,tracer_opt,dt,dx,dy, &
  314. ifms,ifme,jfms,jfme, &
  315. ifts,ifte,jtfs,jfte, &
  316. ids,ide,kds,kde,jds,jde, &
  317. ims,ime,kms,kme,jms,jme, &
  318. its,ite,kts,kte,jts,jte, &
  319. rho,dz8w, & ! input on atmosphere mesh
  320. fgip, fuel_frac_burnt, nfuel_cat, & ! input on fire mesh
  321. chem,tracer) ! output
  322. implicit none
  323. !*** purpose
  324. ! average fire emissions from fire mesh to coarser atmosphereic mesh and add to chemistry arrays
  325. !*** arguments
  326. ! the dimensions are in cells, not nodes!
  327. ! input
  328. integer, intent(in)::chem_opt,tracer_opt
  329. real, intent(in):: dt,dx,dy ! time step & mesh spacing
  330. integer, intent(in)::its,ite,kts,kte,jts,jte,ims,ime,kms,kme,jms,jme &! atm grid dims
  331. ,ids,ide,kds,kde,jds,jde
  332. integer, intent(in)::ifts,ifte,jtfs,jfte,ifms,ifme,jfms,jfme ! fire grid dims
  333. real, intent(in)::rho(ims:ime,kms:kme,jms:jme), & ! air density kg/m^3
  334. dz8w(ims:ime,kms:kme,jms:jme) ! layer height
  335. real, intent(in), dimension(ifms:ifme,jfms:jfme):: fgip, & ! initial fuel load kg/m^2
  336. fuel_frac_burnt, & ! fuel fraction burned this step kg/kg
  337. nfuel_cat ! fuel category (Anderson= 1 to 13)
  338. ! update
  339. real, intent(inout)::chem(ims:ime,kms:kme,jms:jme,num_chem),tracer(ims:ime,kms:kme,jms:jme,num_tracer)
  340. !*** local
  341. integer:: i,i_f,j,j_f,ir,jr,isz1,isz2,jsz1,jsz2,ioff,joff,ibase,jbase,cat,k1,areaw,m,k,k_p,errors
  342. real::fuel_burnt,vol,air,conv, avgw,emis
  343. character(len=128)msg
  344. real, dimension(mfuelcats)::s_fuel,t_fuel,r_fuel ! total per timestep, rate burnt
  345. #ifdef WRF_CHEM
  346. real, dimension(num_chem) ::s_chem,t_chem,r_chem ! total per timestep, rate burnt
  347. real, dimension(num_chem) ::a_chem,g_chem ! concentration in ground level 1
  348. integer, parameter:: chem_np=46
  349. integer:: chem_pointers(chem_np)
  350. character(len=8)::chem_names(chem_np)
  351. #endif
  352. real, dimension(num_tracer) ::s_tracer,t_tracer,r_tracer ! total per timestep, rate burnt
  353. integer, parameter:: tracer_np=8
  354. integer:: tracer_pointers(tracer_np)
  355. character(len=8)::tracer_names(tracer_np)
  356. !*** executable
  357. !check mesh dimensions and domain dimensions
  358. call check_mesh_2dim(its,ite,jts,jte,ims,ime,jms,jme)
  359. call check_mesh_2dim(ifts,ifte,jtfs,jfte,ifms,ifme,jfms,jfme)
  360. if(.not.emis_read)call crash('add_fire_emissions: read_emissions_table must be called first')
  361. write(msg,'(a,i3,a,i3,a,i3)')'add_fire_emissions: chem_opt=',chem_opt,' species ',num_chem,' tracers',num_tracer
  362. call message(msg)
  363. #ifdef WRF_CHEM
  364. chem_pointers= (/ &
  365. p_co, &
  366. p_ch4, &
  367. p_h2, &
  368. p_no, &
  369. p_no2, &
  370. p_so2, &
  371. p_nh3, &
  372. p_p25, &
  373. p_p25i, &
  374. p_p25j, &
  375. p_oc1, &
  376. p_oc2, &
  377. p_bc1, &
  378. p_bc2, &
  379. p_ald, &
  380. p_csl, &
  381. p_eth, &
  382. p_hc3, &
  383. p_hc5, &
  384. p_hcho, &
  385. p_iso, &
  386. p_ket, &
  387. p_mgly, &
  388. p_ol2, &
  389. p_olt, &
  390. p_oli, &
  391. p_ora2,&
  392. p_tol, &
  393. p_xyl, &
  394. p_bigalk, &
  395. p_bigene, &
  396. p_c10h16, &
  397. p_c2h4, &
  398. p_c2h5oh, &
  399. p_c2h6, &
  400. p_c3h6, &
  401. p_c3h8, &
  402. p_ch3cooh, &
  403. p_ch3oh, &
  404. p_cres, &
  405. p_glyald, &
  406. ! p_hyac, &
  407. p_isopr, &
  408. p_macr, &
  409. p_mek, &
  410. p_mvk, &
  411. p_smoke /)
  412. chem_names= (/ &
  413. 'co ', &
  414. 'ch4 ', &
  415. 'h2 ', &
  416. 'no ', &
  417. 'no2 ', &
  418. 'so2 ', &
  419. 'nh3 ', &
  420. 'p25 ', &
  421. 'p25i ', &
  422. 'p25j ', &
  423. 'oc1 ', &
  424. 'oc2 ', &
  425. 'bc1 ', &
  426. 'bc2 ', &
  427. 'ald ', &
  428. 'csl ', &
  429. 'eth ', &
  430. 'hc3 ', &
  431. 'hc5 ', &
  432. 'hcho ', &
  433. 'iso ', &
  434. 'ket ', &
  435. 'mgly ', &
  436. 'ol2 ', &
  437. 'olt ', &
  438. 'oli ', &
  439. 'ora2 ',&
  440. 'tol ', &
  441. 'xyl ', &
  442. 'bigalk ', &
  443. 'bigene ', &
  444. 'c10h16 ', &
  445. 'c2h4 ', &
  446. 'c2h5oh ', &
  447. 'c2h6 ', &
  448. 'c3h6 ', &
  449. 'c3h8 ', &
  450. 'ch3cooh ', &
  451. 'ch3oh ', &
  452. 'cres ', &
  453. 'glyald ', &
  454. ! 'hyac ', &
  455. 'isopr ', &
  456. 'macr ', &
  457. 'mek ', &
  458. 'mvk ', &
  459. 'smoke ' /)
  460. call check_pointers('chem',chem,chem_names,chem_pointers)
  461. #endif
  462. tracer_pointers= (/ &
  463. p_tr17_1, &
  464. p_tr17_2, &
  465. p_tr17_3, &
  466. p_tr17_4, &
  467. p_tr17_5, &
  468. p_tr17_6, &
  469. p_tr17_7, &
  470. p_tr17_8 /)
  471. tracer_names= (/ &
  472. 'tr17_1 ', &
  473. 'tr17_2 ', &
  474. 'tr17_3 ', &
  475. 'tr17_4 ', &
  476. 'tr17_5 ', &
  477. 'tr17_6 ', &
  478. 'tr17_7 ', &
  479. 'tr17_8 ' /)
  480. call check_pointers('tracer',tracer,tracer_names,tracer_pointers)
  481. ! compute mesh sizes
  482. isz1 = ite-its+1
  483. jsz1 = jte-jts+1
  484. isz2 = ifte-ifts+1
  485. jsz2 = jfte-jtfs+1
  486. ! check mesh sizes
  487. if(isz1.le.0.or.jsz1.le.0.or.isz2.le.0.or.jsz2.le.0)then
  488. call message('all mesh sizes must be positive',level=0)
  489. goto 9
  490. endif
  491. ! compute mesh ratios
  492. ir=isz2/isz1
  493. jr=jsz2/jsz1
  494. if(isz2.ne.isz1*ir .or. jsz2.ne.jsz1*jr)then
  495. call message('input mesh size must be multiple of output mesh size',level=0)
  496. goto 9
  497. endif
  498. avgw = 1.0/(ir*jr) ! averaging weight = 1/number of fire cells per atm cell
  499. ! initialize emissions statistics per timestep
  500. #ifdef WRF_CHEM
  501. t_chem = 0.
  502. #endif
  503. t_fuel = 0.
  504. do i=1,num_tracer
  505. t_tracer(i)=0.
  506. enddo
  507. ! conversion fuel_burnt kg/m^2 -> chem_X 1e6*mol/mol
  508. ! emis_X(g/kg)*fuel_burnt(kg/m^2)/mw_X(g/mol) = emissions (mol/m^2)
  509. ! rho(kg/m^3)*dz8w(m))/mw_air(28.97e-3 kg/mol) = dry air in the 1st layer (mol/m^2)
  510. k1 = kts
  511. write(msg,'(a,i3)')'Fire emissions inserted into atmosphere level',k1
  512. call message(msg,level=msglevel)
  513. #ifdef WRF_CHEM
  514. if(fire_print_msg .ge. msglevel .and.printsums .gt. 0)then
  515. ! sum ground concentrations and check for nans
  516. a_chem=0.0
  517. g_chem=0.0
  518. errors=0
  519. do j=jts,jte
  520. do k=1,chem_np
  521. k_p=chem_pointers(k)
  522. do i=its,ite
  523. if(chem(i,k1,j,k_p ).ne.chem(i,k1,j,k_p ))errors=errors+1
  524. a_chem(k_p)=a_chem(k_p)+chem(i,k1,j,k_p )
  525. enddo
  526. enddo
  527. enddo
  528. if(errors>0)call crash('NaN before chem update')
  529. call wrf_dm_sum_reals(a_chem,g_chem)
  530. call message('Layer1 raw sums before adding fire emissions',level=msglevel)
  531. do i=1,chem_np,line
  532. m=min(i+line-1,chem_np)
  533. write(msg,80)'Emissions ',(trim(chem_names(j)),j=i,m)
  534. call message(msg,level=msglevel)
  535. write(msg,81)'Layer1 beg',(g_chem(chem_pointers(j)),j=i,m)
  536. call message(msg,level=msglevel)
  537. call message(' ',level=msglevel)
  538. enddo
  539. endif
  540. #endif
  541. do j=max(jds+1,jts),min(jte,jde-1) ! safe distance from domain boundary
  542. jbase=jtfs+jr*(j-jts) ! indexing
  543. do i=max(ids+1,its),min(ite,ide-1)
  544. ibase=ifts+ir*(i-its) ! indexing
  545. !air = 1e6*mw_air/rho(i,kds,j) ! 1e6*mw_air/air density
  546. !vol = avgw/dz8w(i,kds,j) ! averaging volume factor / 1st layer depth
  547. do joff=0,jr-1
  548. j_f=joff+jbase
  549. do ioff=0,ir-1
  550. i_f=ioff+ibase
  551. !*** fire cell (i_f,j_f) contributes to atmosphere cell (i,j) at ground level
  552. fuel_burnt = fgip(i_f,j_f) * fuel_frac_burnt(i_f,j_f) ! kg/m^2
  553. cat = nfuel_cat(i_f, j_f) ! usually 1 to 13
  554. if(cat.lt.no_fuel_cat)t_fuel(cat)=t_fuel(cat) + fuel_burnt
  555. !*** chem compounds emissions given in g/kg
  556. ! fuel_burnt kg/m^2 * table g/kg -> ppmv = 1e6*mol/mol in 1st layer
  557. !AK rho is in kg/m3 so the conversion factor must be scaled by a 1000 to match
  558. !emissions in grams
  559. ! conv = avgw*1e6*mw_air/(rho(i,k1,j)*dz8w(i,k1,j))
  560. conv = avgw*1e3*mw_air/(rho(i,k1,j)*dz8w(i,k1,j))
  561. #ifdef WRF_CHEM
  562. emis=co (cat)*fuel_burnt ! emission from fire cell in g/m^2
  563. t_chem(p_co) = t_chem(p_co) + emis ! add to total
  564. ! if(isnan(chem(i,k1,j,p_co )))call crash('NaN before')
  565. chem(i,k1,j,p_co )=chem(i,k1,j,p_co ) + emis*conv*imw_co ! add to chem
  566. ! if(isnan(chem(i,k1,j,p_co )))call crash('NaN after')
  567. emis=ch4 (cat)*fuel_burnt ! emission from fire cell in g/m^2
  568. t_chem(p_ch4) = t_chem(p_ch4) + emis ! add to total
  569. chem(i,k1,j,p_ch4 )=chem(i,k1,j,p_ch4 ) + emis*conv*imw_ch4 ! add to chem
  570. emis=h2 (cat)*fuel_burnt ! emission from fire cell in g/m^2
  571. t_chem(p_h2) = t_chem(p_h2) + emis ! add to total
  572. chem(i,k1,j,p_h2 )=chem(i,k1,j,p_h2 ) + emis*conv*imw_h2 ! add to chem
  573. emis=no (cat)*fuel_burnt ! emission from fire cell in g/m^2
  574. t_chem(p_no) = t_chem(p_no) + emis ! add to total
  575. chem(i,k1,j,p_no )=chem(i,k1,j,p_no ) + emis*conv*imw_no ! add to chem
  576. emis=no2 (cat)*fuel_burnt ! emission from fire cell in g/m^2
  577. t_chem(p_no2) = t_chem(p_no2) + emis ! add to total
  578. chem(i,k1,j,p_no2 )=chem(i,k1,j,p_no2 ) + emis*conv*imw_no2 ! add to chem
  579. emis=so2 (cat)*fuel_burnt ! emission from fire cell in g/m^2
  580. t_chem(p_so2) = t_chem(p_so2) + emis ! ads to total
  581. chem(i,k1,j,p_so2 )=chem(i,k1,j,p_so2 ) + emis*conv*imw_so2 ! add to chem
  582. emis=nh3 (cat)*fuel_burnt ! emission from fire cell in g/m^2
  583. t_chem(p_nh3) = t_chem(p_nh3) + emis ! add to total
  584. chem(i,k1,j,p_nh3 )=chem(i,k1,j,p_nh3 ) + emis*conv*imw_nh3 ! add to chem
  585. !*** other emissions already given in mol/kg
  586. ! fuel_burnt kg/m^2 * table mol/kg -> ppmv = 1e6*mol/mol in 1st layer dry air in 1st layer
  587. ! same conversion factor but we will not divide by the molecular weight of the compound
  588. ! conv = avgw*1e6*mw_air/(rho(i,kds,j)*dz8w(i,kds,j))
  589. emis=ald (cat)*fuel_burnt ! emission from fire cell
  590. t_chem(p_ald) = t_chem(p_ald) + emis ! add to total
  591. chem(i,k1,j,p_ald )=chem(i,k1,j,p_ald )+emis*conv
  592. emis=csl (cat)*fuel_burnt ! emission from fire cell
  593. t_chem(p_csl) = t_chem(p_csl) + emis ! add to total
  594. chem(i,k1,j,p_csl )=chem(i,k1,j,p_csl )+emis*conv
  595. emis=eth (cat)*fuel_burnt ! emission from fire cell
  596. t_chem(p_eth) = t_chem(p_eth) + emis ! add to total
  597. chem(i,k1,j,p_eth )=chem(i,k1,j,p_eth )+emis*conv
  598. emis=hc3 (cat)*fuel_burnt ! emission from fire cell
  599. t_chem(p_hc3) = t_chem(p_hc3) + emis ! add to total
  600. chem(i,k1,j,p_hc3 )=chem(i,k1,j,p_hc3 )+emis*conv
  601. emis=hc5 (cat)*fuel_burnt ! emission from fire cell
  602. t_chem(p_hc5) = t_chem(p_hc5) + emis ! add to total
  603. chem(i,k1,j,p_hc5 )=chem(i,k1,j,p_hc5 )+emis*conv
  604. emis=hcho (cat)*fuel_burnt ! emission from fire cell
  605. t_chem(p_hcho) = t_chem(p_hcho) + emis ! add to total
  606. chem(i,k1,j,p_hcho)=chem(i,k1,j,p_hcho)+emis*conv
  607. emis=iso (cat)*fuel_burnt ! emission from fire cell
  608. t_chem(p_iso) = t_chem(p_iso) + emis ! add to total
  609. chem(i,k1,j,p_iso )=chem(i,k1,j,p_iso )+emis*conv
  610. emis=ket (cat)*fuel_burnt ! emission from fire cell
  611. t_chem(p_ket) = t_chem(p_ket) + emis ! add to total
  612. chem(i,k1,j,p_ket )=chem(i,k1,j,p_ket )+emis*conv
  613. emis=mgly (cat)*fuel_burnt ! emission from fire cell
  614. t_chem(p_mgly) = t_chem(p_mgly) + emis ! add to total
  615. chem(i,k1,j,p_mgly)=chem(i,k1,j,p_mgly)+emis*conv
  616. emis=ol2 (cat)*fuel_burnt ! emission from fire cell
  617. t_chem(p_ol2) = t_chem(p_ol2) + emis ! add to total
  618. chem(i,k1,j,p_ol2 )=chem(i,k1,j,p_ol2 )+emis*conv
  619. emis=olt (cat)*fuel_burnt ! emission from fire cell
  620. t_chem(p_olt) = t_chem(p_olt) + emis ! add to total
  621. chem(i,k1,j,p_olt )=chem(i,k1,j,p_olt )+emis*conv
  622. emis=oli (cat)*fuel_burnt ! emission from fire cell
  623. t_chem(p_oli) = t_chem(p_oli) + emis ! add to total
  624. chem(i,k1,j,p_oli )=chem(i,k1,j,p_oli )+emis*conv
  625. emis=ora2 (cat)*fuel_burnt ! emission from fire cell
  626. t_chem(p_ora2) = t_chem(p_ora2) + emis ! add to total
  627. chem(i,k1,j,p_ora2)=chem(i,k1,j,p_ora2)+emis*conv
  628. emis=tol (cat)*fuel_burnt ! emission from fire cell
  629. t_chem(p_tol) = t_chem(p_tol) + emis ! add to total
  630. chem(i,k1,j,p_tol )=chem(i,k1,j,p_tol )+emis*conv
  631. emis=xyl (cat)*fuel_burnt ! emission from fire cell
  632. t_chem(p_xyl) = t_chem(p_xyl) + emis ! add to total
  633. chem(i,k1,j,p_xyl )=chem(i,k1,j,p_xyl )+emis*conv
  634. emis=bigalk (cat)*fuel_burnt ! emission from fire cell
  635. t_chem(p_bigalk) = t_chem(p_bigalk) + emis ! add to total
  636. chem(i,k1,j,p_bigalk )=chem(i,k1,j,p_bigalk )+emis*conv
  637. emis=bigene (cat)*fuel_burnt ! emission from fire cell
  638. t_chem(p_bigene) = t_chem(p_bigene) + emis ! add to total
  639. chem(i,k1,j,p_bigene )=chem(i,k1,j,p_bigene )+emis*conv
  640. emis=c10h16 (cat)*fuel_burnt ! emission from fire cell
  641. t_chem(p_c10h16) = t_chem(p_c10h16) + emis ! add to total
  642. chem(i,k1,j,p_c10h16 )=chem(i,k1,j,p_c10h16 )+emis*conv
  643. emis=c2h4 (cat)*fuel_burnt ! emission from fire cell
  644. t_chem(p_c2h4) = t_chem(p_c2h4) + emis ! add to total
  645. chem(i,k1,j,p_c2h4 )=chem(i,k1,j,p_c2h4 )+emis*conv
  646. emis=c2h5oh (cat)*fuel_burnt ! emission from fire cell
  647. t_chem(p_c2h5oh) = t_chem(p_c2h5oh) + emis ! add to total
  648. chem(i,k1,j,p_c2h5oh )=chem(i,k1,j,p_c2h5oh )+emis*conv
  649. emis=c2h6 (cat)*fuel_burnt ! emission from fire cell
  650. t_chem(p_c2h6) = t_chem(p_c2h6) + emis ! add to total
  651. chem(i,k1,j,p_c2h6 )=chem(i,k1,j,p_c2h6 )+emis*conv
  652. emis=c3h6 (cat)*fuel_burnt ! emission from fire cell
  653. t_chem(p_c3h6) = t_chem(p_c3h6) + emis ! add to total
  654. chem(i,k1,j,p_c3h6 )=chem(i,k1,j,p_c3h6 )+emis*conv
  655. emis=c3h8 (cat)*fuel_burnt ! emission from fire cell
  656. t_chem(p_c3h8) = t_chem(p_c3h8) + emis ! add to total
  657. chem(i,k1,j,p_c3h8 )=chem(i,k1,j,p_c3h8 )+emis*conv
  658. emis=ch3cooh (cat)*fuel_burnt ! emission from fire cell
  659. t_chem(p_ch3cooh) = t_chem(p_ch3cooh) + emis ! add to total
  660. chem(i,k1,j,p_ch3cooh )=chem(i,k1,j,p_ch3cooh )+emis*conv
  661. emis=ch3oh (cat)*fuel_burnt ! emission from fire cell
  662. t_chem(p_ch3oh) = t_chem(p_ch3oh) + emis ! add to total
  663. chem(i,k1,j,p_ch3oh )=chem(i,k1,j,p_ch3oh )+emis*conv
  664. emis=cres (cat)*fuel_burnt ! emission from fire cell
  665. t_chem(p_cres) = t_chem(p_cres) + emis ! add to total
  666. chem(i,k1,j,p_cres )=chem(i,k1,j,p_cres )+emis*conv
  667. emis=glyald (cat)*fuel_burnt ! emission from fire cell
  668. t_chem(p_glyald) = t_chem(p_glyald) + emis ! add to total
  669. chem(i,k1,j,p_glyald )=chem(i,k1,j,p_glyald )+emis*conv
  670. emis=isopr (cat)*fuel_burnt ! emission from fire cell
  671. t_chem(p_isopr) = t_chem(p_isopr) + emis ! add to total
  672. chem(i,k1,j,p_isopr )=chem(i,k1,j,p_isopr )+emis*conv
  673. emis=macr (cat)*fuel_burnt ! emission from fire cell
  674. t_chem(p_macr) = t_chem(p_macr) + emis ! add to total
  675. chem(i,k1,j,p_macr )=chem(i,k1,j,p_macr )+emis*conv
  676. emis=mek (cat)*fuel_burnt ! emission from fire cell
  677. t_chem(p_mek) = t_chem(p_mek) + emis ! add to total
  678. chem(i,k1,j,p_mek )=chem(i,k1,j,p_mek )+emis*conv
  679. emis=mvk (cat)*fuel_burnt ! emission from fire cell
  680. t_chem(p_mvk) = t_chem(p_mvk) + emis ! add to total
  681. chem(i,k1,j,p_mvk )=chem(i,k1,j,p_mvk )+emis*conv
  682. ! aerosols
  683. ! fuel_burnt kg/m^2 * table g/kg -> ug/kg dry air in 1st layer
  684. ! see also chem/emissions_driver.F line 515
  685. conv = avgw*1e6/(rho(i,k1,j)*dz8w(i,k1,j))
  686. emis=p25 (cat)*fuel_burnt ! emission from fire cell
  687. t_chem(p_p25) = t_chem(p_p25) + emis ! add to total
  688. chem(i,k1,j,p_p25 )=chem(i,k1,j,p_p25 )+emis*conv
  689. emis=p25i (cat)*fuel_burnt ! emission from fire cell
  690. t_chem(p_p25i) = t_chem(p_p25i) + emis ! add to total
  691. chem(i,k1,j,p_p25i )=chem(i,k1,j,p_p25i )+emis*conv
  692. emis=p25j (cat)*fuel_burnt ! emission from fire cell
  693. t_chem(p_p25j) = t_chem(p_p25j) + emis ! add to total
  694. chem(i,k1,j,p_p25j )=chem(i,k1,j,p_p25j )+emis*conv
  695. emis=oc1 (cat)*fuel_burnt ! emission from fire cell
  696. t_chem(p_oc1 ) = t_chem(p_oc1 ) + emis ! add to total
  697. chem(i,k1,j,p_oc1 )=chem(i,k1,j,p_oc1 )+emis*conv
  698. emis=oc2 (cat)*fuel_burnt ! emission from fire cell
  699. t_chem(p_oc2 ) = t_chem(p_oc2 ) + emis ! add to total
  700. chem(i,k1,j,p_oc2 )=chem(i,k1,j,p_oc2 )+emis*conv
  701. emis=bc1 (cat)*fuel_burnt ! emission from fire cell
  702. t_chem(p_bc1 ) = t_chem(p_bc1 ) + emis ! add to total
  703. chem(i,k1,j,p_bc1 )=chem(i,k1,j,p_bc1 )+emis*conv
  704. emis=bc2 (cat)*fuel_burnt ! emission from fire cell
  705. t_chem(p_bc2 ) = t_chem(p_bc2 ) + emis ! add to total
  706. chem(i,k1,j,p_bc2 )=chem(i,k1,j,p_bc2 )+emis*conv
  707. #endif
  708. if (num_tracer >0)then
  709. ! treat tracers exactly the same as aerosols, emissions g/kg fuel burned, tracer concentration ug/kg dry air
  710. conv = avgw*1e6/(rho(i,k1,j)*dz8w(i,k1,j))
  711. emis=tr17_1 (cat)*fuel_burnt ! emission from fire cell
  712. t_tracer(p_tr17_1) = t_tracer(p_tr17_1) + emis ! add to total
  713. tracer(i,k1,j,p_tr17_1 )=tracer(i,k1,j,p_tr17_1 )+emis*conv
  714. emis=tr17_2 (cat)*fuel_burnt ! emission from fire cell
  715. t_tracer(p_tr17_2) = t_tracer(p_tr17_2) + emis ! add to total
  716. tracer(i,k1,j,p_tr17_2 )=tracer(i,k1,j,p_tr17_2 )+emis*conv
  717. emis=tr17_3 (cat)*fuel_burnt ! emission from fire cell
  718. t_tracer(p_tr17_3) = t_tracer(p_tr17_3) + emis ! add to total
  719. tracer(i,k1,j,p_tr17_3 )=tracer(i,k1,j,p_tr17_3 )+emis*conv
  720. emis=tr17_4 (cat)*fuel_burnt ! emission from fire cell
  721. t_tracer(p_tr17_4) = t_tracer(p_tr17_4) + emis ! add to total
  722. tracer(i,k1,j,p_tr17_4 )=tracer(i,k1,j,p_tr17_4 )+emis*conv
  723. emis=tr17_5 (cat)*fuel_burnt ! emission from fire cell
  724. t_tracer(p_tr17_5) = t_tracer(p_tr17_5) + emis ! add to total
  725. tracer(i,k1,j,p_tr17_5 )=tracer(i,k1,j,p_tr17_5 )+emis*conv
  726. emis=tr17_6 (cat)*fuel_burnt ! emission from fire cell
  727. t_tracer(p_tr17_6) = t_tracer(p_tr17_6) + emis ! add to total
  728. tracer(i,k1,j,p_tr17_6 )=tracer(i,k1,j,p_tr17_6 )+emis*conv
  729. emis=tr17_7 (cat)*fuel_burnt ! emission from fire cell
  730. t_tracer(p_tr17_7) = t_tracer(p_tr17_7) + emis ! add to total
  731. tracer(i,k1,j,p_tr17_7 )=tracer(i,k1,j,p_tr17_7 )+emis*conv
  732. emis=tr17_8 (cat)*fuel_burnt ! emission from fire cell
  733. t_tracer(p_tr17_8) = t_tracer(p_tr17_8) + emis ! add to total
  734. tracer(i,k1,j,p_tr17_8 )=tracer(i,k1,j,p_tr17_8 )+emis*conv
  735. endif
  736. enddo
  737. enddo
  738. enddo
  739. enddo
  740. #ifdef WRF_CHEM
  741. if(fire_print_msg .ge. msglevel .and.printsums .gt. 0)then
  742. ! sum ground concentrations and check for nans
  743. a_chem=0.0
  744. g_chem=0.0
  745. errors=0
  746. do j=jts,jte
  747. do k=1,chem_np
  748. k_p=chem_pointers(k)
  749. do i=its,ite
  750. if(chem(i,k1,j,k_p ).ne.chem(i,k1,j,k_p ))errors=errors+1
  751. a_chem(k_p)=a_chem(k_p)+chem(i,k1,j,k_p )
  752. enddo
  753. enddo
  754. enddo
  755. if(errors>0)call crash('NaN after chem update')
  756. call wrf_dm_sum_reals(a_chem,g_chem)
  757. call message('Layer1 raw sums after adding fire emissions',level=msglevel)
  758. do i=1,chem_np,line
  759. m=min(i+line-1,chem_np)
  760. write(msg,80)'Emissions ',(trim(chem_names(j)),j=i,m)
  761. call message(msg,level=msglevel)
  762. write(msg,81)'Layer1 end',(g_chem(chem_pointers(j)),j=i,m)
  763. call message(msg,level=msglevel)
  764. call message(' ',level=msglevel)
  765. enddo
  766. endif
  767. #endif
  768. if(fire_print_msg .ge. msglevel .and.printsums .gt. 0)then
  769. ! sum over processes and add to cumulative sums
  770. ! fuel burned
  771. call wrf_dm_sum_reals(t_fuel,s_fuel)
  772. ! scale
  773. s_fuel = s_fuel*dx*dy
  774. ! get rates
  775. r_fuel = s_fuel/dt
  776. ! add to cumulative totals
  777. if(size(c_fuel).ne.nfuelcats)call crash('add_fire_emissions: bad size c_fuel')
  778. c_fuel = c_fuel + s_fuel
  779. #ifdef WRF_CHEM
  780. call wrf_dm_sum_reals(a_chem,g_chem)
  781. ! chem
  782. call wrf_dm_sum_reals(t_chem,s_chem)
  783. s_chem = s_chem*dx*dy
  784. r_chem = s_chem/dt
  785. if(size(c_chem).ne.num_chem)call crash('add_fire_emissions: bad size c_chem')
  786. c_chem = c_chem + s_chem
  787. call message('Total emissions in g or mol per the table',level=msglevel)
  788. do i=1,chem_np,line
  789. m=min(i+line-1,chem_np)
  790. write(msg,80)'Emissions ',(trim(chem_names(j)),j=i,m)
  791. call message(msg,level=msglevel)
  792. write(msg,81)'Cumulative',(c_chem(chem_pointers(j)),j=i,m)
  793. call message(msg,level=msglevel)
  794. write(msg,81)'Rate per s',(r_chem(chem_pointers(j)),j=i,m)
  795. call message(msg,level=msglevel)
  796. call message(' ',level=msglevel)
  797. enddo
  798. #endif
  799. if(num_tracer >0)then
  800. ! tracer
  801. call wrf_dm_sum_reals(t_tracer,s_tracer)
  802. s_tracer = s_tracer*dx*dy
  803. r_tracer = s_tracer/dt
  804. if(size(c_tracer).ne.num_tracer)call crash('add_fire_emissions: bad size c_tracer')
  805. c_tracer = c_tracer + s_tracer
  806. call message('Total emissions in g',level=msglevel)
  807. do i=1,tracer_np,line
  808. m=min(i+line-1,tracer_np)
  809. write(msg,80)'Emissions ',(trim(tracer_names(j)),j=i,m)
  810. call message(msg,level=msglevel)
  811. write(msg,81)'Cumulative',(c_tracer(tracer_pointers(j)),j=i,m)
  812. call message(msg,level=msglevel)
  813. write(msg,81)'Rate per s',(r_tracer(tracer_pointers(j)),j=i,m)
  814. call message(msg,level=msglevel)
  815. call message(' ',level=msglevel)
  816. enddo
  817. endif
  818. do cat=1,nfuelcats
  819. if(c_fuel(cat) > 0.)then
  820. write(msg,83)fuel_name(cat),' burned',c_fuel(cat),'kg, rate',r_fuel(cat),' kg/s'
  821. call message(msg,level=msglevel)
  822. endif
  823. enddo
  824. write(msg,83)'Total fuel',' burned',sum(c_fuel),'kg, rate',sum(r_fuel),' kg/s'
  825. call message(msg,level=msglevel)
  826. endif
  827. 80 format(a,8a11)
  828. 81 format(a,8e11.3)
  829. 83 format(a30,a,g14.4,a,g14.4,a,a)
  830. return
  831. 9 continue
  832. !$OMP CRITICAL(SFIRE_ATM_CRIT)
  833. write(msg,91)ifts,ifte,jtfs,jfte,ifms,ifme,jfms,jfme
  834. call message(msg,level=0)
  835. write(msg,91)its,ite,jts,jte,ims,ime,jms,jme
  836. call message(msg,level=0)
  837. write(msg,92)'input mesh size:',isz2,jsz2
  838. call message(msg,level=0)
  839. 91 format('dimensions: ',8i8)
  840. write(msg,92)'output mesh size:',isz1,jsz1
  841. call message(msg,level=0)
  842. 92 format(a,2i8)
  843. !$OMP END CRITICAL(SFIRE_ATM_CRIT)
  844. call crash('add_fire_emissions: bad mesh sizes')
  845. end subroutine add_fire_emissions
  846. !
  847. !***
  848. !
  849. subroutine check_pointers(array_name,array,pointer_names,pointers)
  850. implicit none
  851. !*** arguments
  852. character(len=*)::array_name
  853. real, dimension(:,:,:,:)::array
  854. character(len=*), dimension(:)::pointer_names
  855. integer, dimension(:)::pointers
  856. !*** local
  857. integer::np,i,m,j
  858. character(len=256)::msg
  859. !** executable
  860. np=ubound(pointers,1)
  861. 993 format(3a,4(1x,i3,':',i3))
  862. !$OMP CRITICAL(SFIRE_ATM_CRIT)
  863. write(msg,993)'array ',array_name,' has dimensions ',&
  864. lbound(array,1),ubound(array,1), &
  865. lbound(array,2),ubound(array,2), &
  866. lbound(array,3),ubound(array,3), &
  867. lbound(array,4),ubound(array,4)
  868. call message(msg)
  869. do i=1,np,line
  870. m=min(i+line-1,np)
  871. write(msg,'(a,8(1x,a8))')'Species',(trim(pointer_names(j)),j=i,m)
  872. call message(msg,level=msglevel)
  873. write(msg,'(a,8i9)') 'Pointer',(pointers(j),j=i,m)
  874. call message(msg,level=msglevel)
  875. call message(' ')
  876. enddo
  877. if(maxval(pointers) > ubound(array,4) .or. minval(pointers) < lbound(array,4))then
  878. write(msg,'(3a)')'add_fire_emissions: a ',array_name,' pointer is out of bounds'
  879. call crash(msg)
  880. endif
  881. !$OMP END CRITICAL(SFIRE_ATM_CRIT)
  882. end subroutine check_pointers
  883. !
  884. !***
  885. !
  886. SUBROUTINE fire_tendency( &
  887. ids,ide, kds,kde, jds,jde, & ! dimensions
  888. ims,ime, kms,kme, jms,jme, &
  889. its,ite, kts,kte, jts,jte, &
  890. grnhfx,grnqfx,canhfx,canqfx, & ! heat fluxes summed up to atm grid
  891. alfg,alfc,z1can, & ! coeffients, properties, geometry
  892. zs,z_at_w,dz8w,mu,rho, &
  893. rthfrten,rqvfrten) ! theta and Qv tendencies
  894. ! This routine is atmospheric physics
  895. ! it does NOT go into module_fr_sfire_phys because it is not fire physics
  896. ! taken from the code by Ned Patton, only order of arguments change to the convention here
  897. ! --- this routine takes fire generated heat and moisture fluxes and
  898. ! calculates their influence on the theta and water vapor
  899. ! --- note that these tendencies are valid at the Arakawa-A location
  900. IMPLICIT NONE
  901. ! --- incoming variables
  902. INTEGER , INTENT(in) :: ids,ide, kds,kde, jds,jde, &
  903. ims,ime, kms,kme, jms,jme, &
  904. its,ite, kts,kte, jts,jte
  905. REAL, INTENT(in), DIMENSION( ims:ime,jms:jme ) :: grnhfx,grnqfx ! W/m^2
  906. REAL, INTENT(in), DIMENSION( ims:ime,jms:jme ) :: canhfx,canqfx ! W/m^2
  907. REAL, INTENT(in), DIMENSION( ims:ime,jms:jme ) :: zs ! topography (m abv sealvl)
  908. REAL, INTENT(in), DIMENSION( ims:ime,jms:jme ) :: mu ! dry air mass (Pa)
  909. REAL, INTENT(in), DIMENSION( ims:ime,kms:kme,jms:jme ) :: z_at_w ! m abv sealvl
  910. REAL, INTENT(in), DIMENSION( ims:ime,kms:kme,jms:jme ) :: dz8w ! dz across w-lvl
  911. REAL, INTENT(in), DIMENSION( ims:ime,kms:kme,jms:jme ) :: rho ! density
  912. REAL, INTENT(in) :: alfg ! extinction depth ground fire heat (m)
  913. REAL, INTENT(in) :: alfc ! extinction depth crown fire heat (m)
  914. REAL, INTENT(in) :: z1can ! height of crown fire heat release (m)
  915. ! --- outgoing variables
  916. REAL, INTENT(out), DIMENSION( ims:ime,kms:kme,jms:jme ) :: &
  917. rthfrten, & ! theta tendency from fire (in mass units)
  918. rqvfrten ! Qv tendency from fire (in mass units)
  919. ! --- local variables
  920. INTEGER :: i,j,k
  921. INTEGER :: i_st,i_en, j_st,j_en, k_st,k_en
  922. REAL :: cp_i
  923. REAL :: rho_i
  924. REAL :: xlv_i
  925. REAL :: z_w
  926. REAL :: fact_g, fact_c
  927. REAL :: alfg_i, alfc_i
  928. REAL, DIMENSION( its:ite,kts:kte,jts:jte ) :: hfx,qfx
  929. !! character(len=128)::msg
  930. do j=jts,jte
  931. do k=kts,min(kte+1,kde)
  932. do i=its,ite
  933. rthfrten(i,k,j)=0.
  934. rqvfrten(i,k,j)=0.
  935. enddo
  936. enddo
  937. enddo
  938. ! --- set some local constants
  939. cp_i = 1./cp ! inverse of specific heat
  940. xlv_i = 1./xlv ! inverse of latent heat
  941. alfg_i = 1./alfg
  942. alfc_i = 1./alfc
  943. !!write(msg,'(8e11.3)')cp,cp_i,xlv,xlv_i,alfg,alfc,z1can
  944. !!call message(msg)
  945. call print_2d_stats(its,ite,jts,jte,ims,ime,jms,jme,grnhfx,'fire_tendency:grnhfx')
  946. call print_2d_stats(its,ite,jts,jte,ims,ime,jms,jme,grnqfx,'fire_tendency:grnqfx')
  947. ! --- set loop indicies : note that
  948. i_st = MAX(its,ids+1)
  949. i_en = MIN(ite,ide-1)
  950. k_st = kts
  951. k_en = MIN(kte,kde-1)
  952. j_st = MAX(jts,jds+1)
  953. j_en = MIN(jte,jde-1)
  954. ! --- distribute fluxes
  955. DO j = j_st,j_en
  956. DO k = k_st,k_en
  957. DO i = i_st,i_en
  958. ! --- set z (in meters above ground)
  959. z_w = z_at_w(i,k,j) - zs(i,j) ! should be zero when k=k_st
  960. ! --- heat flux
  961. fact_g = cp_i * EXP( - alfg_i * z_w )
  962. IF ( z_w < z1can ) THEN
  963. fact_c = cp_i
  964. ELSE
  965. fact_c = cp_i * EXP( - alfc_i * (z_w - z1can) )
  966. END IF
  967. hfx(i,k,j) = fact_g * grnhfx(i,j) + fact_c * canhfx(i,j)
  968. !! write(msg,2)i,k,j,z_w,grnhfx(i,j),hfx(i,k,j)
  969. !!2 format('hfx:',3i4,6e11.3)
  970. !! call message(msg)
  971. ! --- vapor flux
  972. fact_g = xlv_i * EXP( - alfg_i * z_w )
  973. IF (z_w < z1can) THEN
  974. fact_c = xlv_i
  975. ELSE
  976. fact_c = xlv_i * EXP( - alfc_i * (z_w - z1can) )
  977. END IF
  978. qfx(i,k,j) = fact_g * grnqfx(i,j) + fact_c * canqfx(i,j)
  979. !! if(hfx(i,k,j).ne.0. .or. qfx(i,k,j) .ne. 0.)then
  980. !! write(msg,1)i,k,j,hfx(i,k,j),qfx(i,k,j)
  981. !!1 format('tend:',3i6,2e11.3)
  982. !! call message(msg)
  983. ! endif
  984. END DO
  985. END DO
  986. END DO
  987. ! --- add flux divergence to tendencies
  988. !
  989. ! multiply by dry air mass (mu) to eliminate the need to
  990. ! call sr. calculate_phy_tend (in dyn_em/module_em.F)
  991. ! print *,'fire_tendency:',i_st,i_en,j_st,j_en
  992. DO j = j_st,j_en
  993. DO k = k_st,k_en-1
  994. DO i = i_st,i_en
  995. rho_i = 1./rho(i,k,j)
  996. rthfrten(i,k,j) = - mu(i,j) * rho_i * (hfx(i,k+1,j)-hfx(i,k,j)) / dz8w(i,k,j)
  997. rqvfrten(i,k,j) = - mu(i,j) * rho_i * (qfx(i,k+1,j)-qfx(i,k,j)) / dz8w(i,k,j)
  998. ! print *,i,j,k,rthfrten(i,k,j)
  999. END DO
  1000. END DO
  1001. END DO
  1002. call print_3d_stats(its,ite,kts,kte,jts,jte,ims,ime,kms,kme,jms,jme,rthfrten,'fire_tendency:rthfrten')
  1003. call print_3d_stats(its,ite,kts,kte,jts,jte,ims,ime,kms,kme,jms,jme,rqvfrten,'fire_tendency:rqvfrten')
  1004. RETURN
  1005. END SUBROUTINE fire_tendency
  1006. !
  1007. !***
  1008. !
  1009. subroutine interpolate_atm2fire(id, & ! for debug output, <= 0 no output
  1010. ids,ide, kds,kde, jds,jde, & ! atm grid dimensions
  1011. ims,ime, kms,kme, jms,jme, &
  1012. ips,ipe,jps,jpe, &
  1013. its,ite,jts,jte, &
  1014. ifds, ifde, jfds, jfde, & ! fire grid dimensions
  1015. ifms, ifme, jfms, jfme, &
  1016. ifps, ifpe, jfps, jfpe, & ! fire patch bounds
  1017. ifts,ifte,jfts,jfte, &
  1018. ir,jr, & ! atm/fire grid ratio
  1019. u_frame, v_frame, & ! velocity frame correction
  1020. u,v, & ! atm grid arrays in
  1021. ph,phb, &
  1022. z0,zs, &
  1023. uah,vah, &
  1024. uf,vf) ! fire grid arrays out
  1025. implicit none
  1026. ! Jan Mandel, October 2010
  1027. !*** purpose: interpolate winds and height
  1028. !*** arguments
  1029. integer, intent(in)::id
  1030. integer, intent(in):: &
  1031. ids,ide, kds,kde, jds,jde, & ! atm domain bounds
  1032. ims,ime, kms,kme, jms,jme, & ! atm memory bounds
  1033. ips,ipe,jps,jpe, &
  1034. its,ite,jts,jte, & ! atm tile bounds
  1035. ifds, ifde, jfds, jfde, & ! fire domain bounds
  1036. ifms, ifme, jfms, jfme, & ! fire memory bounds
  1037. ifps, ifpe, jfps, jfpe, & ! fire patch bounds
  1038. ifts,ifte,jfts,jfte, & ! fire tile bounds
  1039. ir,jr ! atm/fire grid refinement ratio
  1040. real, intent(in):: u_frame, v_frame ! velocity frame correction
  1041. real,intent(in),dimension(ims:ime,kms:kme,jms:jme)::&
  1042. u,v, & ! atm wind velocity, staggered
  1043. ph,phb ! geopotential
  1044. real,intent(in),dimension(ims:ime,jms:jme)::&
  1045. z0, & ! roughness height
  1046. zs ! terrain height
  1047. real,intent(out),dimension(ims:ime,jms:jme)::&
  1048. uah, & ! atm wind at fire_wind_height, diagnostics
  1049. vah !
  1050. real,intent(out), dimension(ifms:ifme,jfms:jfme)::&
  1051. uf,vf ! wind velocity fire grid nodes
  1052. !*** local
  1053. character(len=256)::msg
  1054. #define TDIMS its-2,ite+2,jts-2,jte+2
  1055. real, dimension(its-2:ite+2,jts-2:jte+2):: ua,va ! atm winds, interpolated over height, still staggered grid
  1056. real, dimension(its-2:ite+2,kds:kde,jts-2:jte+2):: altw,altub,altvb,hgtu,hgtv ! altitudes
  1057. integer:: i,j,k,ifts1,ifte1,jfts1,jfte1,ite1,jte1
  1058. integer::itst,itet,jtst,jtet,itsu,iteu,jtsu,jteu,itsv,itev,jtsv,jtev
  1059. integer::kdmax,its1,jts1,ips1,jps1
  1060. integer::itsou,iteou,jtsou,jteou,itsov,iteov,jtsov,jteov
  1061. real:: ground,loght,loglast,logz0,logfwh,ht,zr
  1062. real::r_nan
  1063. integer::i_nan
  1064. equivalence (i_nan,r_nan)
  1065. !*** executable
  1066. ! debug init local arrays
  1067. i_nan=2147483647
  1068. ua=r_nan
  1069. va=r_nan
  1070. altw=r_nan
  1071. altub=r_nan
  1072. hgtu=r_nan
  1073. hgtv=r_nan
  1074. if(kds.ne.1)then
  1075. !$OMP CRITICAL(SFIRE_DRIVER_CRIT)
  1076. write(msg,*)'WARNING: bottom index kds=',kds,' should be 1?'
  1077. call message(msg)
  1078. !$OMP END CRITICAL(SFIRE_DRIVER_CRIT)
  1079. endif
  1080. ! ^ j
  1081. ! ------------ |
  1082. ! | | ----> i
  1083. ! u p |
  1084. ! | | nodes in cell (i,j)
  1085. ! ------v----- view from top
  1086. !
  1087. ! v(ide,jde+1)
  1088. ! -------x------
  1089. ! | |
  1090. ! | |
  1091. ! u(ide,jde) x x x u(ide+1,jde)
  1092. ! | p(ide,hde) |
  1093. ! | | p=ph,phb,z0,...
  1094. ! -------x------
  1095. ! v(ide,jde)
  1096. !
  1097. ! staggered values set u(ids:ide+1,jds:jde) v(ids:ide,jds:jde+1)
  1098. ! p=ph+phb set at (ids:ide,jds:jde)
  1099. ! location of u(i,j) needs p(i-1,j) and p(i,j)
  1100. ! location of v(i,j) needs p(i,j-1) and p(i,j)
  1101. ! *** NOTE need HALO in ph, phb
  1102. ! so we can compute only u(ids+1:ide,jds:jde) v(ids:ide,jds+1,jde)
  1103. ! unless we extend p at the boundary
  1104. ! but because we care about the fire way in the inside it does not matter
  1105. ! if the fire gets close to domain boundary the simulation is over anyway
  1106. ite1=snode(ite,ide,1)
  1107. jte1=snode(jte,jde,1)
  1108. ! do this in any case to check for nans
  1109. call print_3d_stats(its,ite1,kds,kde,jts,jte,ims,ime,kms,kme,jms,jme,u,'wind U in')
  1110. call print_3d_stats(its,ite,kds,kde,jts,jte1,ims,ime,kms,kme,jms,jme,v,'wind V in')
  1111. if(fire_print_msg.gt.0)then
  1112. !$OMP CRITICAL(SFIRE_DRIVER_CRIT)
  1113. write(msg,'(a,f7.2,a)')'interpolate_atm2fire: log-interpolation of wind to',fire_wind_height,' m'
  1114. call message(msg)
  1115. !$OMP END CRITICAL(SFIRE_DRIVER_CRIT)
  1116. endif
  1117. ! indexing
  1118. ! for w
  1119. itst=ifval(ids.eq.its,its,its-1)
  1120. itet=ifval(ide.eq.ite,ite,ite+1)
  1121. jtst=ifval(jds.ge.jts,jts,jts-1)
  1122. jtet=ifval(jde.eq.jte,jte,jte+1)
  1123. ! for u
  1124. itsu=ifval(ids.eq.its,its+1,its) ! staggered direction
  1125. iteu=ifval(ide.eq.ite,ite,ite+1) ! staggered direction
  1126. jtsu=ifval(jds.ge.jts,jts,jts-1)
  1127. jteu=ifval(jde.eq.jte,jte,jte+1)
  1128. ! for v
  1129. jtsv=ifval(jds.eq.jts,jts+1,jts) ! staggered direction
  1130. jtev=ifval(jde.eq.jte,jte,jte+1) ! staggered direction
  1131. itsv=ifval(ids.ge.its,its,its-1)
  1132. itev=ifval(ide.eq.ite,ite,ite+1)
  1133. if(fire_print_msg.ge.1)then
  1134. !$OMP CRITICAL(SFIRE_DRIVER_CRIT)
  1135. write(msg,7001)'atm input ','tile',its,ite,jts,jte
  1136. call message(msg)
  1137. write(msg,7001)'altw ','tile',itst,itet,jtst,jtet
  1138. call message(msg)
  1139. !$OMP END CRITICAL(SFIRE_DRIVER_CRIT)
  1140. endif
  1141. 7001 format(a,' dimensions ',a4,':',i6,' to ',i6,' by ',i6,' to ',i6)
  1142. !**********************************************************
  1143. !* *
  1144. !* find the altitude of the w points *
  1145. !* *
  1146. !**********************************************************
  1147. !! in future, replace by z8w & test if the same
  1148. kdmax=kde-1 ! max layer to interpolate from, can be less
  1149. do j = jtst,jtet
  1150. do k=kds,kdmax+1
  1151. do i = itst,itet
  1152. altw(i,k,j) = (ph(i,k,j)+phb(i,k,j))/g ! altitude of the bottom w-point
  1153. enddo
  1154. enddo
  1155. enddo
  1156. ! values at u points
  1157. if(fire_print_msg.ge.1)then
  1158. !$OMP CRITICAL(SFIRE_DRIVER_CRIT)
  1159. write(msg,7001)'u interp at','tile',itsu,iteu,jtsu,jteu
  1160. call message(msg)
  1161. !$OMP END CRITICAL(SFIRE_DRIVER_CRIT)
  1162. endif
  1163. !**********************************************************
  1164. !* *
  1165. !* interpolate the altitude from w points to u points *
  1166. !* *
  1167. !**********************************************************
  1168. do j = jtsu,jteu
  1169. do k=kds,kdmax+1
  1170. do i = itsu,iteu
  1171. altub(i,k,j)= 0.5*(altw(i-1,k,j)+altw(i,k,j)) ! altitude of the bottom point under u-point
  1172. enddo
  1173. enddo
  1174. do k=kds,kdmax
  1175. do i = itsu,iteu
  1176. hgtu(i,k,j) = 0.5*(altub(i,k,j)+altub(i,k+1,j)) - altub(i,kds,j) ! height of the u-point above the ground
  1177. enddo
  1178. enddo
  1179. enddo
  1180. ! values at v points
  1181. if(fire_print_msg.ge.1)then
  1182. !$OMP CRITICAL(SFIRE_DRIVER_CRIT)
  1183. write(msg,7001)'v interp at','tile',itsv,itev,jtsv,jtev
  1184. call message(msg)
  1185. !$OMP END CRITICAL(SFIRE_DRIVER_CRIT)
  1186. endif
  1187. !**********************************************************
  1188. !* *
  1189. !* interpolate the altitude from w points to v points *
  1190. !* *
  1191. !**********************************************************
  1192. do j = jtsv,jtev
  1193. do k=kds,kdmax+1
  1194. do i = itsv,itev
  1195. altvb(i,k,j)= 0.5*(altw(i,k,j-1)+altw(i,k,j)) ! altitude of the bottom point under v-point
  1196. enddo
  1197. enddo
  1198. do k=kds,kdmax
  1199. do i = itsv,itev
  1200. hgtv(i,k,j) = 0.5*(altvb(i,k,j)+altvb(i,k+1,j)) - altvb(i,kds,j) ! height of the v-point above the ground
  1201. enddo
  1202. enddo
  1203. enddo
  1204. #ifdef DEBUG_OUT
  1205. call write_array_m3(itsu,iteu,kds,kdmax,jtsu,jteu,its-2,ite+2,kds,kde,jts-2,jte+2,altub,'altub',id)
  1206. call write_array_m3(itsv,itev,kds,kdmax,jtsv,jtev,its-2,ite+2,kds,kde,jts-2,jte+2,altvb,'altvb',id)
  1207. call write_array_m3(itsu,iteu,kds,kdmax,jtsu,jteu,its-2,

Large files files are truncated, but you can click here to view the full file