1 ! the main program is at the end because of fortran limitations
3 #define NF_TYPE NF90_FLOAT
9 subroutine check(status)
11 integer, intent ( in) :: status
13 if(status /= nf90_noerr) then
14 print *, nf90_strerror(status)
22 module module_model_test
23 use module_fr_sfire_util
24 use module_fr_sfire_model
25 use module_fr_sfire_phys
36 integer:: nx,ny, msteps ! problem dimension, in cells, number of steps
37 real:: fdx,fdy, dt,wind,alpha ! fire mesh spacing (m), time step (s), wind azimuth
38 integer::rfx,rfy ! refinement, convenience only
60 print *,'nx=',nx,' ny=',ny,' msteps=',msteps,' fdx=',fdx,' fdy=',fdy,' dt=',dt,' wind=',wind,' alpha=',alpha
61 call model_test(1,nx,1,ny, &
65 fdx,fdy,wind,alpha,dt,msteps)
67 end subroutine main_sub
74 subroutine model_test( &
75 ifds,ifde,jfds,jfde, &
76 ifms,ifme,jfms,jfme, &
77 ifps,ifpe,jfps,jfpe, &
78 fdx,fdy,wind,alpha,dt,msteps)
82 integer, intent(in):: &
83 ifds,ifde,jfds,jfde, &
84 ifps,ifpe,jfps,jfpe, &
85 ifms,ifme,jfms,jfme, msteps
86 real, intent(in)::fdx,fdy,dt,wind,alpha
89 real, dimension(ifms:ifme,jfms:jfme):: zsf, &
92 integer:: num_ignitions,i,j,ifuelread,istep,nfuel_cat0,ifun,ifun_start
93 logical::need_lfn_update
94 real:: t0,time_start,sm,sn
95 integer, dimension(ifms:ifme,jfms:jfme)::nfuel_cat,ischap
96 real, dimension(ifms:ifme,jfms:jfme)::fuel_time,vx,vy,dzfsdx,dzfsdy,bbb,betafl,phiwc,r_0,fgip
97 integer, parameter::max_tiles=10
98 integer::num_tiles,ij,ifts,ifte,jfts,jfte
99 integer, dimension(max_tiles)::if_start,if_end,jf_start,jf_end
100 integer, parameter :: max_ignitions=10
101 real, dimension(max_ignitions) :: ignition_start_x,ignition_start_y, &
102 ignition_end_x,ignition_end_y,ignition_radius,ignition_time
103 character (len=NF90_MAX_NAME), parameter :: iofile = "fire_io.nc"
104 integer :: ncid,xid,yid,tid,lfnid,vfxid,vfyid,tignid,grnhftid,itmp,tdim,tvalsid
105 integer :: xsid,ysid ! staggered dims
106 integer :: ostat,stepnum,grnqftid,fuel_fracid,zsfid,fueltimeid
108 integer,parameter :: ndims = 3
109 integer,dimension(ndims):: dimids,count,start,atmp,counts,starts
114 call set_tiles(2,2,ifps,ifpe,jfps,jfpe,num_tiles,if_start,if_end,jf_start,jf_end)
116 print *,'mesh size in cells: ',ifps,ifpe,jfps,jfpe
117 print *,'array allocation: ',ifms,ifme,jfms,jfme
119 t0=0 ! starting time, arbitrary
120 ostat=nf90_open(iofile,NF90_WRITE,ncid)
121 print*,ostat,nf90_noerr
122 if(ostat.ne.NF90_NOERR)then
125 ! populate the arrays somehow
128 zsf(i,j)=1000 ! flat ground
129 vx(i,j)=wind*cos(alpha) ! constant wind
130 vy(i,j)=wind*sin(alpha)
133 call check( nf90_create(iofile,NF90_NOCLOBBER,ncid) )
134 call check( nf90_def_dim(ncid,"x",ifpe-ifps+1,xid) )
135 call check( nf90_def_dim(ncid,"y",jfpe-jfps+1,yid) )
136 call check( nf90_def_dim(ncid,"x_stag",ifpe-ifps+2,xsid) )
137 call check( nf90_def_dim(ncid,"y_stag",jfpe-jfps+2,ysid) )
138 call check( nf90_def_dim(ncid,"Time",NF90_UNLIMITED,tid) )
139 call check( nf90_put_att(ncid,NF90_GLOBAL,"DX",fdx) )
140 call check( nf90_put_att(ncid,NF90_GLOBAL,"DY",fdy) )
142 call check( nf90_put_att(ncid,NF90_GLOBAL,"stepnum",stepnum) )
144 dimids=(/xsid,ysid,tid/)
145 call check( nf90_def_var(ncid,"lfn",NF_TYPE,dimids,lfnid) )
146 call check( nf90_def_var(ncid,"vx",NF_TYPE,dimids,vfxid) )
147 call check( nf90_def_var(ncid,"vy",NF_TYPE,dimids,vfyid) )
148 call check( nf90_def_var(ncid,"Times",NF_TYPE,(/tid/),tvalsid) )
150 dimids=(/xid,yid,tid/)
151 call check( nf90_def_var(ncid,"tign",NF_TYPE,dimids,tignid) )
152 call check( nf90_def_var(ncid,"grnhfx",NF_TYPE,dimids,grnhftid) )
153 call check( nf90_def_var(ncid,"grnqfx",NF_TYPE,dimids,grnqftid) )
154 call check( nf90_def_var(ncid,"fuelfrac",NF_TYPE,dimids,fuel_fracid) )
155 call check( nf90_def_var(ncid,"fueltime",NF_TYPE,dimids,fueltimeid) )
156 call check( nf90_enddef(ncid) )
163 call check( nf90_inq_dimid(ncid,"x_stag",xsid) )
164 call check( nf90_inquire_dimension(ncid,xsid,len=itmp) )
165 if(itmp.ne.ifpe-ifps+2)call check(NF90_EVARSIZE)
166 call check( nf90_inq_dimid(ncid,"y_stag",ysid) )
167 call check( nf90_inquire_dimension(ncid,ysid,len=itmp) )
168 if(itmp.ne.jfpe-jfps+2)call check(NF90_EVARSIZE)
170 call check( nf90_inq_dimid(ncid,"x",xid) )
171 call check( nf90_inquire_dimension(ncid,xid,len=itmp) )
172 if(itmp.ne.ifpe-ifps+1)call check(NF90_EVARSIZE)
173 call check( nf90_inq_dimid(ncid,"y",yid) )
174 call check( nf90_inquire_dimension(ncid,yid,len=itmp) )
175 if(itmp.ne.jfpe-jfps+1)call check(NF90_EVARSIZE)
176 call check( nf90_inq_dimid(ncid,"Time",tid) )
177 call check( nf90_inquire(ncid,unlimitedDimID=itmp) )
178 if(itmp.ne.tid)call check(NF90_EVARSIZE)
180 call check( nf90_inq_varid(ncid,"lfn",lfnid) )
181 call check( nf90_inq_varid(ncid,"vx",vfxid) )
182 call check( nf90_inq_varid(ncid,"vy",vfyid) )
183 call check( nf90_inq_varid(ncid,"tign",tignid) )
184 call check( nf90_inq_varid(ncid,"grnhfx",grnhftid) )
185 call check( nf90_inq_varid(ncid,"grnqfx",grnqftid) )
186 call check( nf90_inq_varid(ncid,"fuelfrac",fuel_fracid) )
187 call check( nf90_inq_varid(ncid,"fueltime",fueltimeid) )
188 call check( nf90_inquire_dimension(ncid,tid,len=tdim) )
189 call check( nf90_inq_varid(ncid,"Times",tvalsid) )
190 call check( nf90_get_var(ncid,tvalsid,atmp,start=(/tdim/),count=(/1/)) )
192 dimids=(/xid,yid,tid/)
193 call check( nf90_get_att(ncid,nf90_global,"stepnum",stepnum) )
195 count=(/ifpe-ifps+1,jfpe-jfps+1,1/)
196 counts=(/ifpe-ifps+2,jfpe-jfps+2,1/)
200 #define _SD (ifps:ifpe+1,jfps:jfpe+1)
201 #define _D (ifps:ifpe,jfps:jfpe)
202 call check( nf90_get_var(ncid,lfnid,lfn _SD,start=starts,count=counts) )
203 call check( nf90_get_var(ncid,tignid,tign _D,start=starts,count=count) )
204 call check( nf90_get_var(ncid,vfxid,vx _SD,start=starts,count=counts) )
205 call check( nf90_get_var(ncid,vfyid,vy _SD,start=starts,count=counts) )
206 call check( nf90_get_var(ncid,grnhftid,grnhfx _D,start=start,count=count) )
207 call check( nf90_get_var(ncid,grnqftid,grnqfx _D,start=start,count=count) )
208 call check( nf90_get_var(ncid,fuel_fracid,fuel_frac _D,start=start,count=count) )
209 call check( nf90_get_var(ncid,fueltimeid,fuel_time _D,start=start,count=count) )
213 count=(/ifpe-ifps+1,jfpe-jfps+1,1/)
214 counts=(/ifpe-ifps+2,jfpe-jfps+2,1/)
221 open(1,file='model_test_out.txt',form='formatted')
230 ignition_start_x(1)=0.5*fdx*(ifde-ifds)
231 ignition_start_y(1)=0.5*fdy*(jfde-jfds)
232 ignition_end_x(1)=0.5*fdx*(ifde-ifds)*0.9999999
233 ignition_end_y(1)=0.5*fdy*(jfde-jfds)*1.0000001
234 ignition_radius(1) = 0.5*max(5.0,6*max(fdx,fdy))
236 ignition_start_x(2)=1000
237 ignition_start_y(2)=500
238 ignition_end_x(2)=1500
239 ignition_end_y(2)=1500
240 ! at least 6 by 6 cells but no less than 5 m
241 ignition_radius(2) = 0.5*max(5.0,6*max(fdx,fdy))
249 do istep=sstep,msteps
251 if(istep.ne.1)ifun_start=3
253 !OMP PARALLEL DO PRIVATE(ij,ifts,ifte,jfts,jfte)
260 call sfire_model (10*istep+ij,ifun, &
261 need_lfn_update, num_ignitions, &
262 ifuelread,nfuel_cat0, &
263 ifds,ifde,jfds,jfde, & ! fire domain dims - the whole domain
264 ifms,ifme,jfms,jfme, & ! fire memory dims - how declared
265 ifts,ifte,jfts,jfte, & ! fire tile dims - this thread
266 time_start,dt, & ! time and increment
267 fdx,fdy, & ! fire mesh spacing
268 2, & ! boundary_guard
269 ignition_start_x,ignition_start_y, &
270 ignition_end_x,ignition_end_y, &
273 zsf, & ! terrain height (for gradient)
274 vx,vy, & ! input: wind
275 lfn,lfn_out,tign,fuel_frac, & ! state: level function, ign time, fuel left
276 grnhfx,grnqfx, & ! output: heat fluxes
277 nfuel_cat, & ! fuel data per point
278 fuel_time, & ! save derived internal data
279 dzfsdx,dzfsdy,bbb,betafl,phiwc,r_0,fgip,ischap &
285 nf90_put_var(ncid,tvalsid,atmp,start=(/start(3)/),count=(/count(3)/)) &
287 call check( nf90_put_var(ncid,lfnid,lfn _SD,start=start,count=counts) )
288 call check( nf90_put_var(ncid,tignid,tign _D,start=start,count=count) )
289 call check( nf90_put_var(ncid,vfxid,vx _SD,start=start,count=counts) )
290 call check( nf90_put_var(ncid,vfyid,vy _SD,start=start,count=counts) )
291 call check( nf90_put_var(ncid,grnhftid,grnhfx _D,start=start,count=count) )
292 call check( nf90_put_var(ncid,grnqftid,grnqfx _D,start=start,count=count) )
293 call check( nf90_put_var(ncid,fuel_fracid,fuel_frac _D,start=start,count=count) )
294 call check( nf90_put_var(ncid,tvalsid,atmp,start=(/tdim/),count=(/1/)) )
295 call check( nf90_put_var(ncid,fueltimeid,fuel_time _D,start=start,count=count) )
296 call check( nf90_put_att(ncid,nf90_global,"stepnum",istep) )
297 call check( nf90_sync(ncid) )
298 time_start=time_start+dt
301 call check( nf90_close(ncid) )
307 if(istep.le.10.or.mod(istep,10).eq.0)then
308 write(1,1)1.,1.,time_start
309 write(1,1)sm,sn,((lfn(i,j),i=ifps,ifpe),j=jfps,jfpe)
310 write(1,1)sm,sn,((tign(i,j),i=ifps,ifpe),j=jfps,jfpe)
311 write(1,1)sm,sn,((vx(i,j),i=ifps,ifpe),j=jfps,jfpe)
312 write(1,1)sm,sn,((vy(i,j),i=ifps,ifpe),j=jfps,jfpe)
313 write(1,1)sm,sn,((grnhfx(i,j),i=ifps,ifpe),j=jfps,jfpe)
315 print *,'test_main: step ',istep,' of ',msteps,' time ',time_start
316 time_start=time_start+dt
321 end subroutine model_test
324 !******************************
327 subroutine set_tiles(itiles,jtiles,ids,ide,jds,jde,num_tiles,i_start,i_end,j_start,j_end)
328 !*** set tiles for standalone/testing
331 integer,intent(in)::itiles,jtiles,ids,ide,jds,jde
332 integer,intent(out)::num_tiles
333 integer,intent(out),dimension(itiles*jtiles)::i_start,i_end,j_start,j_end
335 integer::i,j,istep,jstep,ij
336 num_tiles=itiles*jtiles
337 istep=(ide-ids+itiles)/itiles
338 jstep=(jde-jds+jtiles)/jtiles
342 i_start(ij)=min(ide,ids+(i-1)*istep)
343 i_end(ij) =min(ide,ids+(i )*istep-1)
344 j_start(ij)=min(jde,jds+(j-1)*jstep)
345 j_end(ij) =min(jde,jds+(j )*jstep-1)
348 call check_tiles(ids,ide,jds,jde,num_tiles,i_start,i_end,j_start,j_end)
349 end subroutine set_tiles
352 subroutine check_tiles(ips,ipe,jps,jpe,num_tiles,i_start,i_end,j_start,j_end)
354 !*** purpose: check if tiles fit
356 integer,intent(in)::ips,ipe,jps,jpe,num_tiles
357 integer,intent(in),dimension(num_tiles)::i_start,i_end,j_start,j_end
359 character(len=128)::msg
362 if(num_tiles.lt.1)call crash('check_tiles: need at least one tile')
364 if (num_tiles.eq.1) then
365 if(i_start(1).ne.ips.or.i_end(1).ne.ipe.or.j_start(1).ne.jps.or.j_end(1).ne.jpe)ie=1
368 if(i_start(ij).lt.ips.or.i_end(ij).gt.ipe &
369 .or.j_start(ij).lt.jps.or.j_end(ij).gt.jpe)ie=ij
373 write(msg,*)'bad tile ',ie
375 write(msg,*)'patch dimensions:',ips,ipe,jps,jpe
378 write(msg,*)'tile',ij,i_start(ij),i_end(ij),j_start(ij),j_end(ij)
381 call crash('bad tile bounds')
383 end subroutine check_tiles
386 end module module_model_test
389 !******************************
393 program model_test_main
394 use module_model_test
396 end program model_test_main