13 ifds
, ifde
, kfds
, kfde
, jfds
, jfde
, & ! fire domain bounds
14 ifms
, ifme
, kfms
, kfme
, jfms
, jfme
, & ! fire memory bounds
15 ifps
, ifpe
, kfps
, kfpe
, jfps
, jfpe
, & ! fire patch bounds
16 ifts
, ifte
, kfts
, kfte
, jfts
, jfte
! fire tile bounds
18 ! declarations of A, msize included from module femwind
20 ! variables read from wrfout
21 real, pointer:: u0_fmw(:,:,:), v0_fmw(:,:,:), w0_fmw(:,:,:), zsfe(:,:), ht_fmw(:), zsf_fmw(:,:), fwh_fmw(:,:)
23 ! variables allocated and computed here
24 real, pointer:: u0(:,:,:), v0(:,:,:), w0(:,:,:), hth(:)
25 real, pointer:: u(:,:,:), v(:,:,:), w(:,:,:), uf(:,:), vf(:,:), wh(:,:)
26 integer, pointer:: kh(:,:)
28 integer:: i
, j
, k
, n(3), nx
, ny
, nz
, nfx
, nfy
, nfz
, iu
=10
29 integer::ncid
,sr(2),frame0_fmw
,dims(3)
30 real:: rate
,A(3,3),dx
,dy
,zx
,zy
31 character(len
=256)::filename
, msg
35 frame
= 1, & ! frame to use in the communication file
36 frame_terminate
= -99, &
38 mframe
= 10, & ! send code to terminate and exit after this frame
44 namelist /femwind_nl
/ &
48 mframe
, & ! send code to terminate and exit after this frame
55 filename
= "wrf.nc" ! file to read from and write to
57 ! params from namelist
58 open(iu
,file
="namelist.femwind")
63 !************************************
65 !************************************
67 call ncopen(filename
,nf90_nowrite
,ncid
)
69 ! fire subgrid refinement ratio, 3d grid dimensions cell centered
70 call get_wrf_dims(ncid
,sr
,dims
)
71 ! horizontal mesh spacing
72 dx
= netcdf_read_att(ncid
,"DX")/sr(1)
73 dy
= netcdf_read_att(ncid
,"DY")/sr(2)
75 ! height of the vertical layers above the terrain
76 call netcdf_read_array_wrf(ncid
,"HT_FMW",frame
=frame
,a1d
=ht_fmw
)
78 ! fire mesh size in cells
83 ! terrain height at cell centers
84 call netcdf_read_array_wrf(ncid
,"ZSF",frame
=frame
,a2d
=zsf_fmw
)
86 ! fire wind height to interpolate to at cell centers
87 call netcdf_read_array_wrf(ncid
,"FWH",frame
=frame
,a2d
=fwh_fmw
)
91 !************************************
93 !************************************
97 params
%A
= reshape((/1.0,0.0,0.0, &
103 mg(1)%nx
= nfx
+ 1 ! dimensions are vertex centered
104 mg(1)%ny
= nfy
+ 1 ! dimensions are vertex centered
105 mg(1)%nz
= nfz
+ 1 ! dimensions are vertex centered
107 call get_mg_dims(mg(1), & ! set bounds compatible with WRF
108 ifds
, ifde
, kfds
,kfde
, jfds
, jfde
, & ! fire grid dimensions
109 ifms
, ifme
, kfms
,kfme
, jfms
, jfme
, &
110 ifps
, ifpe
, kfps
,kfpe
, jfps
, jfpe
, & ! fire patch bounds
111 ifts
, ifte
, kfts
,kfte
, jfts
, jfte
)
113 ! allocations persistent over the whole run
115 allocate(mg(1)%X(ifms
:ifme
,kfms
:kfme
,jfms
:jfme
))
116 allocate(mg(1)%Y(ifms
:ifme
,kfms
:kfme
,jfms
:jfme
))
117 allocate(mg(1)%Z(ifms
:ifme
,kfms
:kfme
,jfms
:jfme
))
118 allocate(u0(ifms
:ifme
,kfms
:kfme
,jfms
:jfme
)) ! vector components called u v W
119 allocate(v0(ifms
:ifme
,kfms
:kfme
,jfms
:jfme
))
120 allocate(w0(ifms
:ifme
,kfms
:kfme
,jfms
:jfme
))
121 allocate(u(ifms
:ifme
,kfms
:kfme
,jfms
:jfme
)) ! vector components called u v W
122 allocate(v(ifms
:ifme
,kfms
:kfme
,jfms
:jfme
))
123 allocate(w(ifms
:ifme
,kfms
:kfme
,jfms
:jfme
))
124 allocate(uf(ifts
:ifte
,jfts
:jfte
))
125 allocate(vf(ifts
:ifte
,jfts
:jfte
))
126 allocate(kh(ifts
:ifte
,jfts
:jfte
))
127 allocate(wh(ifts
:ifte
,jfts
:jfte
))
128 allocate(zsfe(ifts
-1:ifte
+1,jfts
-1:jfte
+1))
130 write(msg
,*)"shape(uf)=",shape(uf
)
132 write(msg
,*)"shape(vf)=",shape(vf
)
135 ! X Y Z are corner based, upper bound larger by one
138 zsfe(ifts
:ifte
,jfts
:jfte
)=zsf_fmw
139 ! extrapolate on sides
140 zsfe(ifts
-1,jfts
:jfte
)=1.5*zsfe(ifts
,jfts
:jfte
)-0.5*zsfe(ifts
+1,jfts
:jfte
)
141 zsfe(ifte
+1,jfts
:jfte
)=1.5*zsfe(ifte
,jfts
:jfte
)-0.5*zsfe(ifte
-1,jfts
:jfte
)
142 zsfe(ifts
:ifte
,jfts
-1)=1.5*zsfe(ifts
:ifte
,jfts
)-0.5*zsfe(ifts
:ifte
,jfts
+1)
143 zsfe(ifts
:ifte
,jfte
+1)=1.5*zsfe(ifts
:ifte
,jfte
)-0.5*zsfe(ifts
:ifte
,jfte
-1)
144 ! extrapolate at domain corners
145 zsfe(ifts
-1,jfts
-1)=1.5*zsfe(ifts
,jfts
)-0.5*zsfe(ifts
+1,jfts
+1)
146 zsfe(ifte
+1,jfts
-1)=1.5*zsfe(ifte
,jfts
)-0.5*zsfe(ifte
-1,jfts
+1)
147 zsfe(ifts
-1,jfte
+1)=1.5*zsfe(ifts
,jfte
)-0.5*zsfe(ifts
+1,jfte
-1)
148 zsfe(ifte
+1,jfte
+1)=1.5*zsfe(ifte
,jfte
)-0.5*zsfe(ifte
-1,jfte
-1)
149 ! interpolate to cell corners
150 mg(1)%Z(ifts
:ifte
+1,kfts
,jfts
:jfte
+1) = 0.25 * ( &
151 zsfe(ifts
:ifte
+1,jfts
:jfte
+1) + &
152 zsfe(ifts
-1:ifte
,jfts
:jfte
+1) + &
153 zsfe(ifts
:ifte
+1,jfts
-1:jfte
) + &
154 zsfe(ifts
-1:ifte
,jfts
-1:jfte
) )
156 ! (X,Y) is the same uniform grid on all levels
160 mg(1)%X(i
,k
,j
) = (i
-1)*dx
161 mg(1)%Y(i
,k
,j
) = (j
-1)*dy
166 ! add top of levels above terrain to Z(:,kfts,:)
167 print *,'debug ht_fmw=',ht_fmw
171 mg(1)%Z(i
,k
,j
) = mg(1)%Z(i
,kfts
,j
) + ht_fmw(k
- kfts
)
179 allocate(mg(1)%dz(mg(1)%nz
-1))
181 mg(1)%dz(k
)=mg(1)%Z(1,k
+1,1)-mg(1)%Z(1,k
,1)
184 ! heights of wind nodes in cell centers
185 allocate(hth(0:kfte
))
189 hth(k
)=0.5*(ht_fmw(k
-1)+ht_fmw(k
))
192 ! indices to interpolate to fwh_fmw
196 if (hth(k
) .ge
. fwh_fmw(i
,j
))then
198 wh(i
,j
) = (hth(k
) - fwh_fmw(i
,j
))/(hth(k
) - hth(k
-1)) ! weight 0 if at the top
199 ! write(msg,*)'i,j=',i,j,'k=',k,'hth=',hth(k),hth(k-1),'fwh=',fwh_fmw(i,j),'wh=',wh(i,j)
204 call crash('did not find interpolation layer')
209 deallocate(hth
,ht_fmw
,zsfe
) ! no longer needed
211 if(call_femwind
.gt
.0)then
212 call message('calling femwind_setup')
213 call femwind_setup(mg
)
214 call message('femwind_setup done')
217 if(write_debug
.gt
.0)then
218 ! write coordinates for debug/display, even if the caller knows
219 call write_average_to_center(mg(1)%X
,'X_c')
220 call write_average_to_center(mg(1)%Y
,'Y_c')
221 call write_average_to_center(mg(1)%Z
,'Z_c')
224 !************************************
225 ! loop over time steps
226 !************************************
228 do frame0_fmw
=1,mframe
230 ! read initial velocity field, loop until delivered
231 call read_initial_wind(filename
,u0_fmw
,v0_fmw
,w0_fmw
,frame0_fmw
,frame
=frame
)
233 ! copy the input data to tile sized bounds
234 ! initial wind is at cell centers, indexing was already switched to ikj in reading
235 u0(ifts
:ifte
,kfts
:kfte
,jfts
:jfte
) = u0_fmw
236 v0(ifts
:ifte
,kfts
:kfte
,jfts
:jfte
) = v0_fmw
237 w0(ifts
:ifte
,kfts
:kfte
,jfts
:jfte
) = w0_fmw
239 ! save memory while solver is running
240 deallocate(u0_fmw
,v0_fmw
,w0_fmw
)
242 ! compute/update mass consistent flow
244 if(call_femwind
.gt
.0)then
245 write(*,'(a)')'calling femwind_solve'
246 call femwind_solve( mg
,&
247 ifds
, ifde
, kfds
, kfde
, jfds
, jfde
, & ! fire domain bounds
248 ifms
, ifme
, kfms
, kfme
, jfms
, jfme
, & ! fire memory bounds
249 ifps
, ifpe
, kfps
, kfpe
, jfps
, jfpe
, & ! fire patch bounds
250 ifts
, ifte
, kfts
, kfte
, jfts
,jfte
, & ! fire tile bounds
251 u0
, v0
, w0
, & ! input arrays
252 u
, v
, w
, & ! output arrays
254 write(*,'(a)')'femwind_solve done'
259 write(*,'(a)')'femwind_solve skipped'
262 if(interpolate_uf_vf
.gt
.0)then
263 ! interpolate u,v to fire height
268 uf(i
,j
) = wh(i
,j
) * u(i
,k
,j
) + (1.0 - wh(i
,j
)) * u(i
,k
-1,j
)
269 vf(i
,j
) = wh(i
,j
) * v(i
,k
,j
) + (1.0 - wh(i
,j
)) * v(i
,k
-1,j
)
277 call message('TESTING ONLY: copying lowest level of input to uf vf')
278 uf
= u0(ifts
:ifte
,1,jfts
:jfte
)
279 vf
= v0(ifts
:ifte
,1,jfts
:jfte
)
282 ! write_fire_wind(filename,frame0_fmw,uf,vf,u_fmw,v_fmw,w_fmw,frame)
283 if(write_uvw_fmw
.gt
.0)then
284 call write_fire_wind(filename
,frame0_fmw
,uf
,vf
, &
285 u(ifts
:ifte
,kfts
:kfte
,jfts
:jfte
), &
286 v(ifts
:ifte
,kfts
:kfte
,jfts
:jfte
), &
287 w(ifts
:ifte
,kfts
:kfte
,jfts
:jfte
), frame
=frame
)
289 call write_fire_wind(filename
,frame0_fmw
,uf
,vf
,frame
=frame
)
292 if(write_debug
.gt
.0)then
293 ! write output as is in 3D but with tight dimensions
294 call write_array(u(ifts
:ifte
,kfts
:kfte
,jfts
:jfte
),'u')
295 call write_array(v(ifts
:ifte
,kfts
:kfte
,jfts
:jfte
),'v')
296 call write_array(w(ifts
:ifte
,kfts
:kfte
,jfts
:jfte
),'w')
297 call write_scalar(rate
,'rate')
302 call write_fire_wind(filename
,frame_terminate
,uf
,vf
)
304 print *,'femwind end'
308 subroutine write_average_to_center(F
,name
)
309 ! average and return with tight bounds
312 real, intent(in
)::F(ifms
:ifme
, kfms
:kfme
, jfms
:jfme
)
313 character(len
=*)::name
315 real, allocatable
::Fm(:,:,:)
319 allocate(Fm(ifts
:ifte
,kfts
:kfte
,jfts
:jfte
))
327 s
= s
+ F(i
+ii
,k
+kk
,j
+jj
)
335 call write_array(Fm
,name
)
336 end subroutine write_average_to_center
338 end program femwind_wrfout