PageRenderTime 49ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/standalone/fire.F

http://github.com/jbeezley/wrf-fire
FORTRAN Legacy | 406 lines | 214 code | 55 blank | 137 comment | 15 complexity | df1124336baf8761fe6e2cc323bb3615 MD5 | raw file
Possible License(s): AGPL-1.0
  1. module module_fire_standalone
  2. use module_fr_sfire_driver, only: set_flags, fire_ignition_convert, &
  3. set_fp_from_grid
  4. use module_fr_sfire_util, only: message,crash, &
  5. lines_type, print_2d_stats
  6. use module_fr_sfire_phys, only: fire_params, init_fuel_cats
  7. use module_fr_sfire_model, only: sfire_model
  8. use module_domain, only: domain
  9. use module_configure, only: grid_config_rec_type,read_namelist
  10. use wrf_netcdf, only : grid_info, read_info, &
  11. create_output_file,write_vars, &
  12. read_vars, debug_print
  13. implicit none
  14. contains
  15. subroutine sub_main
  16. !*** purpose: standalone driver with compatible files to WRF-Fire
  17. implicit none
  18. !*** local
  19. ! arguments to SFIRE
  20. type(domain)::grid ! all: state+inputs+outputs, compatible with wrf
  21. TYPE (grid_config_rec_type):: config_flags ! the namelist
  22. integer:: & ! fire mesh dimensions
  23. ifds,ifde,jfds,jfde, & ! the physical domain
  24. ifps,ifpe,jfps,jfpe, & ! patch - assigned to one process. Here the same as domain.
  25. ifts,ifte,jfts,jfte, & ! memory allocated, needs a strip around the patch
  26. ifms,ifme,jfms,jfme ! memory allocated, needs a strip around the patch
  27. ! I/O interface
  28. character(len=*),parameter::inputfile='fire_input.nc'
  29. character(len=*),parameter::outputfile='fire_output.nc'
  30. real, pointer, dimension(:,:) :: uf1, vf1, uf2, vf2, fmc_g1, fmc_g2 ! stored input fields
  31. ! other derived types
  32. type(grid_info)::info ! dimensions, grid controls
  33. ! scalars
  34. integer:: nsteps,itimestep,ifun_start,ifun_end,id,ifun,iframe,istep
  35. integer::nhalo=5
  36. double precision:: dt_double,duration_s,frame_s ! may need more accurate time computation to get the number of timesteps right
  37. real:: time_start,dt,t
  38. logical::do_ouput
  39. TYPE(lines_type) :: ignition, hfx
  40. type(fire_params)::fp
  41. logical::restart=.false.,uniform=.false.
  42. integer::iframe_start,iframe_end
  43. logical::run_fuel_moisture=.false.
  44. !*** executable
  45. call read_namelist(config_flags) ! read flags from namelist.input
  46. call set_flags(config_flags) ! copy configuration flags to sfire internal structures
  47. debug_print = config_flags%fire_print_msg.ge.2 ! if we write a lot
  48. call read_info(inputfile,info) ! get dimensions
  49. ! start empty NetCDF file with the dimensions
  50. call create_output_file(outputfile,info)
  51. ! set dimensions
  52. ifds=1
  53. ifde=info%nfirex
  54. jfds=1
  55. jfde=info%nfirey
  56. ifms=ifds-nhalo
  57. ifme=ifde+nhalo
  58. jfms=ifds-nhalo
  59. jfme=ifde+nhalo
  60. ifps=1
  61. ifpe=ifde
  62. jfps=1
  63. jfpe=jfde
  64. ifts=1
  65. ifte=ifde
  66. jfts=1
  67. jfte=jfde
  68. write(6,2)'fire domain dimensions ',ifds,ifde,jfds,jfde
  69. write(6,2)'fire memory dimensions ',ifms,ifme,jfms,jfme
  70. write(6,2)'fire patch dimensions ',ifps,ifpe,jfps,jfpe
  71. write(6,2)'fire tile dimensions ',ifts,ifte,jfts,jfte
  72. 2 format(a,6i6)
  73. ! allocate
  74. ! inputs
  75. call allocate2d(grid%uf,ifms,ifme,jfms,jfme,'uf') ! fire winds
  76. call allocate2d(grid%vf,ifms,ifme,jfms,jfme,'vf') ! fire winds
  77. call allocate2d(grid%zsf,ifms,ifme,jfms,jfme,'zsf') ! terrain height
  78. call allocate2d(grid%dzdxf,ifms,ifme,jfms,jfme,'dzdxf') ! terrain grad
  79. call allocate2d(grid%dzdyf,ifms,ifme,jfms,jfme,'dzdyf') ! terrain grad
  80. call allocate2d(grid%fxlong,ifms,ifme,jfms,jfme,'fxlong') !
  81. call allocate2d(grid%fxlat,ifms,ifme,jfms,jfme,'fxlat') !
  82. call allocate2d(grid%nfuel_cat,ifms,ifme,jfms,jfme,'nfuel_cat') !
  83. call allocate2d(grid%fmc_g,ifms,ifme,jfms,jfme,'fmc_g') !
  84. ! state
  85. call allocate2d(grid%bbb,ifms,ifme,jfms,jfme,'bbb') ! spread formula coeff
  86. call allocate2d(grid%betafl,ifms,ifme,jfms,jfme,'betafl') ! spread formula coeff
  87. call allocate2d(grid%phiwc,ifms,ifme,jfms,jfme,'phiwc') ! spread formula coeff
  88. call allocate2d(grid%phisc,ifms,ifme,jfms,jfme,'phisc') ! spread formula coeff
  89. call allocate2d(grid%r_0,ifms,ifme,jfms,jfme,'r_0') ! spread formula coeff
  90. call allocate2d(grid%fgip,ifms,ifme,jfms,jfme,'fgip') ! spread formula coeff
  91. call allocate2d(grid%ischap,ifms,ifme,jfms,jfme,'ischap') ! spread formula coeff
  92. call allocate2d(grid%fuel_time,ifms,ifme,jfms,jfme,'fuel_time') !
  93. call allocate2d(grid%lfn,ifms,ifme,jfms,jfme,'lfn')
  94. call allocate2d(grid%tign_g,ifms,ifme,jfms,jfme,'tign_g')
  95. call allocate2d(grid%fuel_frac,ifms,ifme,jfms,jfme,'fuel_frac')
  96. call allocate2d(grid%fuel_frac_burnt,ifms,ifme,jfms,jfme,'fuel_frac_burnt')
  97. call allocate2d(grid%lfn_out,ifms,ifme,jfms,jfme,'lfn_out')
  98. ! outputs
  99. call allocate2d(grid%fire_area,ifms,ifme,jfms,jfme,'fire_area')
  100. call allocate2d(grid%ros,ifms,ifme,jfms,jfme,'ros')
  101. call allocate2d(grid%flineint,ifms,ifme,jfms,jfme,'flineint')
  102. call allocate2d(grid%flineint2,ifms,ifme,jfms,jfme,'flineint2')
  103. call allocate2d(grid%fgrnhfx,ifms,ifme,jfms,jfme,'fgrnhfx') !
  104. call allocate2d(grid%fgrnqfx,ifms,ifme,jfms,jfme,'fgrnqfx') !
  105. call allocate2d(grid%fcanhfx,ifms,ifme,jfms,jfme,'fcanhfx') !
  106. call allocate2d(grid%fcanqfx,ifms,ifme,jfms,jfme,'fcanqfx') !
  107. call allocate2d(grid%f_ros,ifms,ifme,jfms,jfme,'f_ros') !
  108. call allocate2d(grid%f_ros0,ifms,ifme,jfms,jfme,'f_ros0') !
  109. call allocate2d(grid%f_rosx,ifms,ifme,jfms,jfme,'f_rosx') !
  110. call allocate2d(grid%f_rosy,ifms,ifme,jfms,jfme,'f_rosy') !
  111. call allocate2d(grid%f_lineint,ifms,ifme,jfms,jfme,'f_lineint') !
  112. call allocate2d(grid%f_lineint2,ifms,ifme,jfms,jfme,'f_lineint2') !
  113. call allocate2d(grid%f_int,ifms,ifme,jfms,jfme,'f_int') !
  114. ! local
  115. call allocate2d(uf1,ifms,ifme,jfms,jfme,'uf1') ! fire winds
  116. call allocate2d(vf1,ifms,ifme,jfms,jfme,'vf1') ! fire winds
  117. call allocate2d(uf2,ifms,ifme,jfms,jfme,'uf2') ! fire winds
  118. call allocate2d(vf2,ifms,ifme,jfms,jfme,'vf2') ! fire winds
  119. call allocate2d(fmc_g1,ifms,ifme,jfms,jfme,'fmc_g1') ! moisture
  120. call allocate2d(fmc_g2,ifms,ifme,jfms,jfme,'fmc_g2') ! moisture
  121. ! copy pointers to grid fields, to pass to the spread rate calculation
  122. call set_fp_from_grid(grid,fp)
  123. call init_fuel_cats(.true.)
  124. ! time control
  125. ! NOTE: dt in the netcdf input file as returned in info%dt is WRONG !!
  126. dt_double=config_flags%time_step
  127. if(config_flags%time_step_fract_den.ne.0)then
  128. dt_double=dt_double+dble(config_flags%time_step_fract_num)/dble(config_flags%time_step_fract_den)
  129. endif
  130. duration_s = config_flags%run_seconds &
  131. + 60d0*(config_flags%run_minutes &
  132. + 60d0*(config_flags%run_hours &
  133. + 24d0*(config_flags%run_days)))
  134. if(config_flags%history_interval.ne.0)config_flags%history_interval_m=config_flags%history_interval
  135. frame_s = config_flags%history_interval_s &
  136. + 60d0*(config_flags%history_interval_m &
  137. + 60d0*(config_flags%history_interval_h &
  138. + 24d0*(config_flags%history_interval_d)))
  139. nsteps = nint( frame_s / dt_double ) ! number of time steps for the duration
  140. dt_double = frame_s / nsteps
  141. dt = dt_double
  142. write(*,'(a,f10.3,a,i6,a,f10.3,a)')'frame ',frame_s,'s ',nsteps,' time steps at ',dt_double,'s'
  143. ! divide up for shared memory parallel execution
  144. !!call set_tiles(1,1,ips,ipe,jps,jpe,grid%num_tiles,grid%i_start,grid%i_end,grid%j_start,grid%j_end)
  145. ! set the scalars in grid type
  146. grid%dt = dt
  147. grid%itimestep=0
  148. grid%u_frame=0.
  149. grid%v_frame=0.
  150. ! start output file
  151. !! call create_output_file(outputfile,info)
  152. if(info%ntimes.lt.3)then
  153. !write(*,'(a,i5)')'ntimes=',info%ntimes
  154. !call crash('need at least 3 steps')
  155. uniform=.true.
  156. call read_vars(inputfile,info,1,grid)
  157. iframe_start=1
  158. iframe_end=int(duration_s/frame_s)
  159. else
  160. uniform=.false.
  161. call read_vars(inputfile,info,2,grid)
  162. iframe_start=3
  163. iframe_end=info%ntimes
  164. uf1=grid%uf
  165. vf1=grid%vf
  166. fmc_g1=grid%fmc_g
  167. endif
  168. print *,'fxlat lower bounds:',lbound(grid%fxlat)
  169. print *,'fxlat upper bounds:',ubound(grid%fxlat)
  170. print *,'fxlat(1,1)=',grid%fxlat(1,1),' fxlat(',ifpe,',',jfpe,')=',grid%fxlat(ifpe,jfpe)
  171. print *,'fxlong lower bounds:',lbound(grid%fxlong)
  172. print *,'fxlong upper bounds:',ubound(grid%fxlong)
  173. print *,'fxlong(1,1)=',grid%fxlong(1,1),' fxlong(',ifpe,',',jfpe,')=',grid%fxlong(ifpe,jfpe)
  174. call print_2d_stats(ifps,ifpe,jfps,jfpe,ifms,ifme,jfms,jfme,grid%fxlong,'fire:fxlong')
  175. call print_2d_stats(ifps,ifpe,jfps,jfpe,ifms,ifme,jfms,jfme,grid%fxlat,'fire:fxlat')
  176. ! get ignition data - should have fxlong fxlat now
  177. call fire_ignition_convert (config_flags,ignition, &
  178. grid%fxlong, grid%fxlat, &
  179. ifds,ifde, jfds,jfde, &
  180. ifms,ifme, jfms,jfme, &
  181. ifps,ifpe, jfps,jfpe )
  182. itimestep = 0
  183. ifun_start=1
  184. do iframe=iframe_start,iframe_end ! interval ending with iframe
  185. if(.not.uniform)then
  186. call read_vars(inputfile,info,iframe,grid)
  187. uf2=grid%uf
  188. vf2=grid%vf
  189. fmc_g2=grid%fmc_g
  190. endif
  191. do istep=1,nsteps
  192. itimestep=info%ntimes * (iframe - 1) + istep
  193. grid%itimestep = itimestep
  194. id=itimestep
  195. ifun_end=6
  196. ! interpolate time
  197. time_start = dt_double * (nsteps * (iframe - 1) + istep - 1)
  198. ! interpolate wind
  199. if(.not.uniform)then
  200. t = (istep - 1.)/real(nsteps)
  201. write(*,'(a,i4,a,i3,a,i8,a,f10.3,a,f10.3)')'frame',iframe,' step',istep,' id',id, &
  202. ' start at ',time_start,'s t=',t
  203. grid%uf = (1. - t)*uf1 + t*uf2
  204. grid%vf = (1. - t)*vf1 + t*vf2
  205. grid%fmc_g = (1. - t)*fmc_g1 + t*fmc_g2
  206. endif
  207. do ifun=ifun_start,ifun_end
  208. if(ifun.eq.4)then
  209. call print_2d_stats(ifts,ifte,jfts,jfte,ifms,ifme,jfms,jfme,fp%fmc_g,'fire:fmc_g')
  210. endif
  211. call sfire_model ( &
  212. id, & ! unique number for prints and debug
  213. ifun, & ! what to do see below
  214. restart, & ! use existing state
  215. run_fuel_moisture, & ! run the moisture model
  216. config_flags%fire_fuel_read,config_flags%fire_fuel_cat, & ! legacy initial constant fuel category
  217. ifds,ifde,jfds,jfde, & ! fire domain dims - the whole domain
  218. ifms,ifme,jfms,jfme, & ! fire memory dims - how declared
  219. ifps,ifpe,jfps,jfpe, & ! patch - nodes owned by this process
  220. ifts,ifte,jfts,jfte, & ! fire tile dims - this thread
  221. time_start,dt, & ! time and increment
  222. info%fdx,info%fdy, & ! fire mesh spacing,
  223. ignition,hfx, & ! small array of ignition line descriptions
  224. grid%fxlong,grid%fxlat, & ! fire mesh coordinates
  225. grid%fire_hfx, & ! given heat flux (experimental)
  226. grid%lfn,grid%lfn_out,grid%tign_g,grid%fuel_frac,grid%fire_area, & ! state: level function, ign time, fuel left, area burning
  227. grid%fuel_frac_burnt, &
  228. grid%fgrnhfx,grid%fgrnqfx, & ! output: heat fluxes
  229. grid%ros,grid%flineint,grid%flineint2, & ! diagnostic variables
  230. grid%f_ros0,grid%f_rosx,grid%f_rosy,grid%f_ros, & ! fire risk spread
  231. grid%f_int,grid%f_lineint,grid%f_lineint2, & ! fire risk intensities
  232. grid%nfuel_cat, & ! fuel data per point
  233. grid%fuel_time,grid%fwh,grid%fz0, & ! save derived internal data
  234. fp &
  235. )
  236. enddo
  237. ifun_start=3
  238. enddo
  239. call write_vars(outputfile,grid,info,iframe)
  240. if(.not.uniform)then
  241. uf1=uf2
  242. vf1=vf2
  243. fmc_g1=fmc_g2
  244. endif
  245. enddo
  246. end subroutine sub_main
  247. !subroutine model_driver(grid,config_flags)
  248. !
  249. !******************************
  250. !
  251. subroutine set_tiles(itiles,jtiles,ips,ipe,jps,jpe,num_tiles,i_start,i_end,j_start,j_end)
  252. !*** set tiles for standalone/testing
  253. implicit none
  254. !*** arguments
  255. integer,intent(in)::itiles,jtiles,ips,ipe,jps,jpe
  256. integer,intent(out)::num_tiles
  257. integer,intent(out),dimension(itiles*jtiles)::i_start,i_end,j_start,j_end
  258. !*** local
  259. integer::i,j,istep,jstep,ij
  260. character(len=128)::msg
  261. write(msg,1)'patch',ips,':',ipe,jps,':',jpe
  262. 1 format(a,5x,i6,a,2i6,a,i6)
  263. call message(msg,level=-1)
  264. !if(ips.ge.ipe.or.jps.ge.jpe)call crash('bad domain bounds')
  265. !num_tiles=itiles*jtiles
  266. !istep=(ipe-ips+itiles)/itiles
  267. !jstep=(jpe-jps+jtiles)/jtiles
  268. !do i=1,itiles
  269. ! do j=1,jtiles
  270. ! ij=j+(i-1)*jtiles
  271. ! i_start(ij)=min(ipe,ips+(i-1)*istep)
  272. ! i_end(ij) =min(ipe,ips+(i )*istep-1)
  273. ! j_start(ij)=min(jpe,jps+(j-1)*jstep)
  274. ! j_end(ij) =min(jpe,jps+(j )*jstep-1)
  275. ! enddo
  276. !enddo
  277. !call check_tiles(ips,ipe,jps,jpe,num_tiles,i_start,i_end,j_start,j_end)
  278. end subroutine set_tiles
  279. subroutine check_tiles(ips,ipe,jps,jpe,num_tiles,i_start,i_end,j_start,j_end)
  280. implicit none
  281. !*** purpose: check if tiles fit
  282. !*** arguments
  283. integer,intent(in)::ips,ipe,jps,jpe,num_tiles
  284. integer,intent(in),dimension(num_tiles)::i_start,i_end,j_start,j_end
  285. !*** local
  286. character(len=128)::msg
  287. integer:: ij,ie
  288. !*** executable
  289. if(num_tiles.lt.1)call crash('check_tiles: need at least one tile')
  290. ie=0
  291. do ij=1,num_tiles
  292. if(i_start(ij).lt.ips.or.i_end(ij).gt.ipe &
  293. .or.j_start(ij).lt.jps.or.j_end(ij).gt.jpe)then
  294. write(msg,1)'patch',ips,':',ipe,jps,':',jpe
  295. 1 format(a,5x,i6,a,2i6,a,i6)
  296. call message(msg,level=-1)
  297. write(msg,2)'tile',ij,i_start(ij),':',i_end(ij),j_start(ij),':',j_end(ij)
  298. 2 format(a,2i6,a,2i6,a,i6)
  299. call message(msg,level=-1)
  300. call crash('bad tile bounds')
  301. endif
  302. enddo
  303. end subroutine check_tiles
  304. subroutine allocate2d(p,ims,ime,jms,jme,s)
  305. !*** allocate a pointer with error checking and initialization
  306. implicit none
  307. !*** arguments
  308. real, pointer, dimension(:,:)::p
  309. integer, intent(in):: ims,ime,jms,jme
  310. character(len=*),intent(in)::s
  311. !*** local
  312. integer::err
  313. !*** executable
  314. if(debug_print)write(6,1) ims,ime,jms,jme,trim(s)
  315. if(associated(p))call crash('already allocated')
  316. 1 format('allocate2d',2(1x,i6,' :',i6),1x,a)
  317. allocate(p(ims:ime,jms:jme),stat=err)
  318. if(err.ne.0)then
  319. write(6,1)ims,ime,jms,jme,trim(s)
  320. call crash('memory allocation failed')
  321. endif
  322. p=0.
  323. end subroutine allocate2d
  324. subroutine allocate3d(p,ims,ime,jms,jme,kms,kme,s)
  325. !*** allocate a pointer with error checking and initialization
  326. implicit none
  327. !*** arguments
  328. real, pointer, dimension(:,:,:)::p
  329. integer, intent(in):: ims,ime,jms,jme,kms,kme
  330. character(len=*),intent(in)::s
  331. !*** local
  332. integer::err
  333. !*** executable
  334. if(debug_print)write(6,1) ims,ime,jms,jme,kms,kme,trim(s)
  335. 1 format('allocate3d',3(1x,i6,' :',i6),1x,a)
  336. if(associated(p))call crash('already allocated')
  337. allocate(p(ims:ime,jms:jme,kms:kme),stat=err)
  338. if(err.ne.0)then
  339. write(6,1)ims,ime,jms,jme,kms,kme,trim(s)
  340. call crash('memory allocation failed')
  341. endif
  342. p=0.
  343. end subroutine allocate3d
  344. end module module_fire_standalone
  345. !
  346. !******************************
  347. !
  348. program fire
  349. use module_fire_standalone, only: sub_main
  350. call sub_main
  351. end program fire