1 !WRF:DRIVER_LAYER:DOMAIN_OBJECT
3 ! Following are the routines contained within this MODULE:
5 ! alloc_and_configure_domain 1. Allocate the space for a single domain (constants
6 ! and null terminate pointers).
7 ! 2. Connect the domains as a linked list.
8 ! 3. Store all of the domain constants.
9 ! 4. CALL alloc_space_field.
11 ! alloc_space_field 1. Allocate space for the gridded data required for
14 ! dealloc_space_domain 1. Reconnect linked list nodes since the current
16 ! 2. CALL dealloc_space_field.
17 ! 3. Deallocate single domain.
19 ! dealloc_space_field 1. Deallocate each of the fields for a particular
22 ! first_loc_integer 1. Find the first incidence of a particular
23 ! domain identifier from an array of domain
28 USE module_driver_constants
33 USE module_domain_type
35 ! In WRFV3, the module_domain_type is defined
36 ! in a separaate source file, frame/module_domain_type.F
37 ! This enables splitting off the alloc_space_field routine
38 ! into a separate file, reducing the size of module_domain
40 ! Now that a "domain" TYPE exists, we can use it to store a few pointers
41 ! to this type. These are primarily for use in traversing the linked list.
42 ! The "head_grid" is always the pointer to the first domain that is
43 ! allocated. This is available and is not to be changed. The others are
44 ! just temporary pointers.
46 TYPE(domain) , POINTER :: head_grid , new_grid , next_grid , old_grid
48 ! To facilitate an easy integration of each of the domains that are on the
49 ! same level, we have an array for the head pointer for each level. This
50 ! removed the need to search through the linked list at each time step to
51 ! find which domains are to be active.
54 TYPE(domain) , POINTER :: first_domain
55 END TYPE domain_levels
57 TYPE(domain_levels) , DIMENSION(max_levels) :: head_for_each_level
59 ! Use this to support debugging features, giving easy access to clock, etc.
60 TYPE(domain), POINTER :: current_grid
61 LOGICAL, SAVE :: current_grid_set = .FALSE.
64 PRIVATE domain_time_test_print
65 PRIVATE test_adjust_io_timestr
67 INTERFACE get_ijk_from_grid
68 MODULE PROCEDURE get_ijk_from_grid1, get_ijk_from_grid2
71 INTEGER, PARAMETER :: max_hst_mods = 1000
75 SUBROUTINE adjust_domain_dims_for_move( grid , dx, dy )
78 TYPE( domain ), POINTER :: grid
79 INTEGER, INTENT(IN) :: dx, dy
81 data_ordering : SELECT CASE ( model_data_order )
82 CASE ( DATA_ORDER_XYZ )
83 grid%sm31 = grid%sm31 + dx
84 grid%em31 = grid%em31 + dx
85 grid%sm32 = grid%sm32 + dy
86 grid%em32 = grid%em32 + dy
87 grid%sp31 = grid%sp31 + dx
88 grid%ep31 = grid%ep31 + dx
89 grid%sp32 = grid%sp32 + dy
90 grid%ep32 = grid%ep32 + dy
91 grid%sd31 = grid%sd31 + dx
92 grid%ed31 = grid%ed31 + dx
93 grid%sd32 = grid%sd32 + dy
94 grid%ed32 = grid%ed32 + dy
96 CASE ( DATA_ORDER_YXZ )
97 grid%sm31 = grid%sm31 + dy
98 grid%em31 = grid%em31 + dy
99 grid%sm32 = grid%sm32 + dx
100 grid%em32 = grid%em32 + dx
101 grid%sp31 = grid%sp31 + dy
102 grid%ep31 = grid%ep31 + dy
103 grid%sp32 = grid%sp32 + dx
104 grid%ep32 = grid%ep32 + dx
105 grid%sd31 = grid%sd31 + dy
106 grid%ed31 = grid%ed31 + dy
107 grid%sd32 = grid%sd32 + dx
108 grid%ed32 = grid%ed32 + dx
110 CASE ( DATA_ORDER_ZXY )
111 grid%sm32 = grid%sm32 + dx
112 grid%em32 = grid%em32 + dx
113 grid%sm33 = grid%sm33 + dy
114 grid%em33 = grid%em33 + dy
115 grid%sp32 = grid%sp32 + dx
116 grid%ep32 = grid%ep32 + dx
117 grid%sp33 = grid%sp33 + dy
118 grid%ep33 = grid%ep33 + dy
119 grid%sd32 = grid%sd32 + dx
120 grid%ed32 = grid%ed32 + dx
121 grid%sd33 = grid%sd33 + dy
122 grid%ed33 = grid%ed33 + dy
124 CASE ( DATA_ORDER_ZYX )
125 grid%sm32 = grid%sm32 + dy
126 grid%em32 = grid%em32 + dy
127 grid%sm33 = grid%sm33 + dx
128 grid%em33 = grid%em33 + dx
129 grid%sp32 = grid%sp32 + dy
130 grid%ep32 = grid%ep32 + dy
131 grid%sp33 = grid%sp33 + dx
132 grid%ep33 = grid%ep33 + dx
133 grid%sd32 = grid%sd32 + dy
134 grid%ed32 = grid%ed32 + dy
135 grid%sd33 = grid%sd33 + dx
136 grid%ed33 = grid%ed33 + dx
138 CASE ( DATA_ORDER_XZY )
139 grid%sm31 = grid%sm31 + dx
140 grid%em31 = grid%em31 + dx
141 grid%sm33 = grid%sm33 + dy
142 grid%em33 = grid%em33 + dy
143 grid%sp31 = grid%sp31 + dx
144 grid%ep31 = grid%ep31 + dx
145 grid%sp33 = grid%sp33 + dy
146 grid%ep33 = grid%ep33 + dy
147 grid%sd31 = grid%sd31 + dx
148 grid%ed31 = grid%ed31 + dx
149 grid%sd33 = grid%sd33 + dy
150 grid%ed33 = grid%ed33 + dy
152 CASE ( DATA_ORDER_YZX )
153 grid%sm31 = grid%sm31 + dy
154 grid%em31 = grid%em31 + dy
155 grid%sm33 = grid%sm33 + dx
156 grid%em33 = grid%em33 + dx
157 grid%sp31 = grid%sp31 + dy
158 grid%ep31 = grid%ep31 + dy
159 grid%sp33 = grid%sp33 + dx
160 grid%ep33 = grid%ep33 + dx
161 grid%sd31 = grid%sd31 + dy
162 grid%ed31 = grid%ed31 + dy
163 grid%sd33 = grid%sd33 + dx
164 grid%ed33 = grid%ed33 + dx
166 END SELECT data_ordering
169 CALL dealloc_space_field ( grid )
171 CALL alloc_space_field ( grid, grid%id , 1 , 2 , .FALSE. , &
172 grid%sd31, grid%ed31, grid%sd32, grid%ed32, grid%sd33, grid%ed33, &
173 grid%sm31, grid%em31, grid%sm32, grid%em32, grid%sm33, grid%em33, &
174 grid%sp31, grid%ep31, grid%sp32, grid%ep32, grid%sp33, grid%ep33, &
175 grid%sp31x, grid%ep31x, grid%sp32x, grid%ep32x, grid%sp33x, grid%ep33x, &
176 grid%sp31y, grid%ep31y, grid%sp32y, grid%ep32y, grid%sp33y, grid%ep33y, &
177 grid%sm31x, grid%em31x, grid%sm32x, grid%em32x, grid%sm33x, grid%em33x, & ! x-xpose
178 grid%sm31y, grid%em31y, grid%sm32y, grid%em32y, grid%sm33y, grid%em33y & ! y-xpose
183 END SUBROUTINE adjust_domain_dims_for_move
186 SUBROUTINE get_ijk_from_grid1 ( grid , &
187 ids, ide, jds, jde, kds, kde, &
188 ims, ime, jms, jme, kms, kme, &
189 ips, ipe, jps, jpe, kps, kpe, &
190 imsx, imex, jmsx, jmex, kmsx, kmex, &
191 ipsx, ipex, jpsx, jpex, kpsx, kpex, &
192 imsy, imey, jmsy, jmey, kmsy, kmey, &
193 ipsy, ipey, jpsy, jpey, kpsy, kpey )
195 TYPE( domain ), INTENT (IN) :: grid
196 INTEGER, INTENT(OUT) :: &
197 ids, ide, jds, jde, kds, kde, &
198 ims, ime, jms, jme, kms, kme, &
199 ips, ipe, jps, jpe, kps, kpe, &
200 imsx, imex, jmsx, jmex, kmsx, kmex, &
201 ipsx, ipex, jpsx, jpex, kpsx, kpex, &
202 imsy, imey, jmsy, jmey, kmsy, kmey, &
203 ipsy, ipey, jpsy, jpey, kpsy, kpey
205 CALL get_ijk_from_grid2 ( grid , &
206 ids, ide, jds, jde, kds, kde, &
207 ims, ime, jms, jme, kms, kme, &
208 ips, ipe, jps, jpe, kps, kpe )
209 data_ordering : SELECT CASE ( model_data_order )
210 CASE ( DATA_ORDER_XYZ )
211 imsx = grid%sm31x ; imex = grid%em31x ; jmsx = grid%sm32x ; jmex = grid%em32x ; kmsx = grid%sm33x ; kmex = grid%em33x ;
212 ipsx = grid%sp31x ; ipex = grid%ep31x ; jpsx = grid%sp32x ; jpex = grid%ep32x ; kpsx = grid%sp33x ; kpex = grid%ep33x ;
213 imsy = grid%sm31y ; imey = grid%em31y ; jmsy = grid%sm32y ; jmey = grid%em32y ; kmsy = grid%sm33y ; kmey = grid%em33y ;
214 ipsy = grid%sp31y ; ipey = grid%ep31y ; jpsy = grid%sp32y ; jpey = grid%ep32y ; kpsy = grid%sp33y ; kpey = grid%ep33y ;
215 CASE ( DATA_ORDER_YXZ )
216 imsx = grid%sm32x ; imex = grid%em32x ; jmsx = grid%sm31x ; jmex = grid%em31x ; kmsx = grid%sm33x ; kmex = grid%em33x ;
217 ipsx = grid%sp32x ; ipex = grid%ep32x ; jpsx = grid%sp31x ; jpex = grid%ep31x ; kpsx = grid%sp33x ; kpex = grid%ep33x ;
218 imsy = grid%sm32y ; imey = grid%em32y ; jmsy = grid%sm31y ; jmey = grid%em31y ; kmsy = grid%sm33y ; kmey = grid%em33y ;
219 ipsy = grid%sp32y ; ipey = grid%ep32y ; jpsy = grid%sp31y ; jpey = grid%ep31y ; kpsy = grid%sp33y ; kpey = grid%ep33y ;
220 CASE ( DATA_ORDER_ZXY )
221 imsx = grid%sm32x ; imex = grid%em32x ; jmsx = grid%sm33x ; jmex = grid%em33x ; kmsx = grid%sm31x ; kmex = grid%em31x ;
222 ipsx = grid%sp32x ; ipex = grid%ep32x ; jpsx = grid%sp33x ; jpex = grid%ep33x ; kpsx = grid%sp31x ; kpex = grid%ep31x ;
223 imsy = grid%sm32y ; imey = grid%em32y ; jmsy = grid%sm33y ; jmey = grid%em33y ; kmsy = grid%sm31y ; kmey = grid%em31y ;
224 ipsy = grid%sp32y ; ipey = grid%ep32y ; jpsy = grid%sp33y ; jpey = grid%ep33y ; kpsy = grid%sp31y ; kpey = grid%ep31y ;
225 CASE ( DATA_ORDER_ZYX )
226 imsx = grid%sm33x ; imex = grid%em33x ; jmsx = grid%sm32x ; jmex = grid%em32x ; kmsx = grid%sm31x ; kmex = grid%em31x ;
227 ipsx = grid%sp33x ; ipex = grid%ep33x ; jpsx = grid%sp32x ; jpex = grid%ep32x ; kpsx = grid%sp31x ; kpex = grid%ep31x ;
228 imsy = grid%sm33y ; imey = grid%em33y ; jmsy = grid%sm32y ; jmey = grid%em32y ; kmsy = grid%sm31y ; kmey = grid%em31y ;
229 ipsy = grid%sp33y ; ipey = grid%ep33y ; jpsy = grid%sp32y ; jpey = grid%ep32y ; kpsy = grid%sp31y ; kpey = grid%ep31y ;
230 CASE ( DATA_ORDER_XZY )
231 imsx = grid%sm31x ; imex = grid%em31x ; jmsx = grid%sm33x ; jmex = grid%em33x ; kmsx = grid%sm32x ; kmex = grid%em32x ;
232 ipsx = grid%sp31x ; ipex = grid%ep31x ; jpsx = grid%sp33x ; jpex = grid%ep33x ; kpsx = grid%sp32x ; kpex = grid%ep32x ;
233 imsy = grid%sm31y ; imey = grid%em31y ; jmsy = grid%sm33y ; jmey = grid%em33y ; kmsy = grid%sm32y ; kmey = grid%em32y ;
234 ipsy = grid%sp31y ; ipey = grid%ep31y ; jpsy = grid%sp33y ; jpey = grid%ep33y ; kpsy = grid%sp32y ; kpey = grid%ep32y ;
235 CASE ( DATA_ORDER_YZX )
236 imsx = grid%sm33x ; imex = grid%em33x ; jmsx = grid%sm31x ; jmex = grid%em31x ; kmsx = grid%sm32x ; kmex = grid%em32x ;
237 ipsx = grid%sp33x ; ipex = grid%ep33x ; jpsx = grid%sp31x ; jpex = grid%ep31x ; kpsx = grid%sp32x ; kpex = grid%ep32x ;
238 imsy = grid%sm33y ; imey = grid%em33y ; jmsy = grid%sm31y ; jmey = grid%em31y ; kmsy = grid%sm32y ; kmey = grid%em32y ;
239 ipsy = grid%sp33y ; ipey = grid%ep33y ; jpsy = grid%sp31y ; jpey = grid%ep31y ; kpsy = grid%sp32y ; kpey = grid%ep32y ;
240 END SELECT data_ordering
241 END SUBROUTINE get_ijk_from_grid1
243 SUBROUTINE get_ijk_from_grid2 ( grid , &
244 ids, ide, jds, jde, kds, kde, &
245 ims, ime, jms, jme, kms, kme, &
246 ips, ipe, jps, jpe, kps, kpe )
250 TYPE( domain ), INTENT (IN) :: grid
251 INTEGER, INTENT(OUT) :: &
252 ids, ide, jds, jde, kds, kde, &
253 ims, ime, jms, jme, kms, kme, &
254 ips, ipe, jps, jpe, kps, kpe
256 data_ordering : SELECT CASE ( model_data_order )
257 CASE ( DATA_ORDER_XYZ )
258 ids = grid%sd31 ; ide = grid%ed31 ; jds = grid%sd32 ; jde = grid%ed32 ; kds = grid%sd33 ; kde = grid%ed33 ;
259 ims = grid%sm31 ; ime = grid%em31 ; jms = grid%sm32 ; jme = grid%em32 ; kms = grid%sm33 ; kme = grid%em33 ;
260 ips = grid%sp31 ; ipe = grid%ep31 ; jps = grid%sp32 ; jpe = grid%ep32 ; kps = grid%sp33 ; kpe = grid%ep33 ;
261 CASE ( DATA_ORDER_YXZ )
262 ids = grid%sd32 ; ide = grid%ed32 ; jds = grid%sd31 ; jde = grid%ed31 ; kds = grid%sd33 ; kde = grid%ed33 ;
263 ims = grid%sm32 ; ime = grid%em32 ; jms = grid%sm31 ; jme = grid%em31 ; kms = grid%sm33 ; kme = grid%em33 ;
264 ips = grid%sp32 ; ipe = grid%ep32 ; jps = grid%sp31 ; jpe = grid%ep31 ; kps = grid%sp33 ; kpe = grid%ep33 ;
265 CASE ( DATA_ORDER_ZXY )
266 ids = grid%sd32 ; ide = grid%ed32 ; jds = grid%sd33 ; jde = grid%ed33 ; kds = grid%sd31 ; kde = grid%ed31 ;
267 ims = grid%sm32 ; ime = grid%em32 ; jms = grid%sm33 ; jme = grid%em33 ; kms = grid%sm31 ; kme = grid%em31 ;
268 ips = grid%sp32 ; ipe = grid%ep32 ; jps = grid%sp33 ; jpe = grid%ep33 ; kps = grid%sp31 ; kpe = grid%ep31 ;
269 CASE ( DATA_ORDER_ZYX )
270 ids = grid%sd33 ; ide = grid%ed33 ; jds = grid%sd32 ; jde = grid%ed32 ; kds = grid%sd31 ; kde = grid%ed31 ;
271 ims = grid%sm33 ; ime = grid%em33 ; jms = grid%sm32 ; jme = grid%em32 ; kms = grid%sm31 ; kme = grid%em31 ;
272 ips = grid%sp33 ; ipe = grid%ep33 ; jps = grid%sp32 ; jpe = grid%ep32 ; kps = grid%sp31 ; kpe = grid%ep31 ;
273 CASE ( DATA_ORDER_XZY )
274 ids = grid%sd31 ; ide = grid%ed31 ; jds = grid%sd33 ; jde = grid%ed33 ; kds = grid%sd32 ; kde = grid%ed32 ;
275 ims = grid%sm31 ; ime = grid%em31 ; jms = grid%sm33 ; jme = grid%em33 ; kms = grid%sm32 ; kme = grid%em32 ;
276 ips = grid%sp31 ; ipe = grid%ep31 ; jps = grid%sp33 ; jpe = grid%ep33 ; kps = grid%sp32 ; kpe = grid%ep32 ;
277 CASE ( DATA_ORDER_YZX )
278 ids = grid%sd33 ; ide = grid%ed33 ; jds = grid%sd31 ; jde = grid%ed31 ; kds = grid%sd32 ; kde = grid%ed32 ;
279 ims = grid%sm33 ; ime = grid%em33 ; jms = grid%sm31 ; jme = grid%em31 ; kms = grid%sm32 ; kme = grid%em32 ;
280 ips = grid%sp33 ; ipe = grid%ep33 ; jps = grid%sp31 ; jpe = grid%ep31 ; kps = grid%sp32 ; kpe = grid%ep32 ;
281 END SELECT data_ordering
282 END SUBROUTINE get_ijk_from_grid2
284 ! return the values for subgrid whose refinement is in grid%sr
285 ! note when using this routine, it does not affect K. For K
286 ! (vertical), it just returns what get_ijk_from_grid does
287 SUBROUTINE get_ijk_from_subgrid ( grid , &
288 ids0, ide0, jds0, jde0, kds0, kde0, &
289 ims0, ime0, jms0, jme0, kms0, kme0, &
290 ips0, ipe0, jps0, jpe0, kps0, kpe0 )
291 TYPE( domain ), INTENT (IN) :: grid
292 INTEGER, INTENT(OUT) :: &
293 ids0, ide0, jds0, jde0, kds0, kde0, &
294 ims0, ime0, jms0, jme0, kms0, kme0, &
295 ips0, ipe0, jps0, jpe0, kps0, kpe0
298 ids, ide, jds, jde, kds, kde, &
299 ims, ime, jms, jme, kms, kme, &
300 ips, ipe, jps, jpe, kps, kpe
301 CALL get_ijk_from_grid ( grid , &
302 ids, ide, jds, jde, kds, kde, &
303 ims, ime, jms, jme, kms, kme, &
304 ips, ipe, jps, jpe, kps, kpe )
306 ide0 = ide * grid%sr_x
307 ims0 = (ims-1)*grid%sr_x+1
308 ime0 = ime * grid%sr_x
309 ips0 = (ips-1)*grid%sr_x+1
310 ipe0 = ipe * grid%sr_x
313 jde0 = jde * grid%sr_y
314 jms0 = (jms-1)*grid%sr_y+1
315 jme0 = jme * grid%sr_y
316 jps0 = (jps-1)*grid%sr_y+1
317 jpe0 = jpe * grid%sr_y
326 END SUBROUTINE get_ijk_from_subgrid
330 ! Default version ; Otherwise module containing interface to DM library will provide
332 SUBROUTINE wrf_patch_domain( id , domdesc , parent, parent_id , parent_domdesc , &
333 sd1 , ed1 , sp1 , ep1 , sm1 , em1 , &
334 sd2 , ed2 , sp2 , ep2 , sm2 , em2 , &
335 sd3 , ed3 , sp3 , ep3 , sm3 , em3 , &
336 sp1x , ep1x , sm1x , em1x , &
337 sp2x , ep2x , sm2x , em2x , &
338 sp3x , ep3x , sm3x , em3x , &
339 sp1y , ep1y , sm1y , em1y , &
340 sp2y , ep2y , sm2y , em2y , &
341 sp3y , ep3y , sm3y , em3y , &
342 bdx , bdy , bdy_mask )
344 ! Wrf_patch_domain is called as part of the process of initiating a new
345 ! domain. Based on the global domain dimension information that is
346 ! passed in it computes the patch and memory dimensions on this
347 ! distributed-memory process for parallel compilation when DM_PARALLEL is
348 ! defined in configure.wrf. In this case, it relies on an external
349 ! communications package-contributed routine, wrf_dm_patch_domain. For
350 ! non-parallel compiles, it returns the patch and memory dimensions based
351 ! on the entire domain. In either case, the memory dimensions will be
352 ! larger than the patch dimensions, since they allow for distributed
353 ! memory halo regions (DM_PARALLEL only) and for boundary regions around
354 ! the domain (used for idealized cases only). The width of the boundary
355 ! regions to be accommodated is passed in as bdx and bdy.
357 ! The bdy_mask argument is a four-dimensional logical array, each element
358 ! of which is set to true for any boundaries that this process's patch
359 ! contains (all four are true in the non-DM_PARALLEL case) and false
360 ! otherwise. The indices into the bdy_mask are defined in
361 ! frame/module_state_description.F. P_XSB corresponds boundary that
362 ! exists at the beginning of the X-dimension; ie. the western boundary;
363 ! P_XEB to the boundary that corresponds to the end of the X-dimension
364 ! (east). Likewise for Y (south and north respectively).
366 ! The correspondence of the first, second, and third dimension of each
367 ! set (domain, memory, and patch) with the coordinate axes of the model
368 ! domain is based on the setting of the variable model_data_order, which
369 ! comes into this routine through USE association of
370 ! module_driver_constants in the enclosing module of this routine,
371 ! module_domain. Model_data_order is defined by the Registry, based on
372 ! the dimspec entries which associate dimension specifiers (e.g. 'k') in
373 ! the Registry with a coordinate axis and specify which dimension of the
374 ! arrays they represent. For WRF, the sd1 , ed1 , sp1 , ep1 , sm1 , and
375 ! em1 correspond to the starts and ends of the global, patch, and memory
376 ! dimensions in X; those with 2 specify Z (vertical); and those with 3
377 ! specify Y. Note that the WRF convention is to overdimension to allow
378 ! for staggered fields so that sd<em>n</em>:ed<em>n</em> are the starts
379 ! and ends of the staggered domains in X. The non-staggered grid runs
380 ! sd<em>n</em>:ed<em>n</em>-1. The extra row or column on the north or
381 ! east boundaries is not used for non-staggered fields.
383 ! The domdesc and parent_domdesc arguments are for external communication
384 ! packages (e.g. RSL) that establish and return to WRF integer handles
385 ! for referring to operations on domains. These descriptors are not set
386 ! or used otherwise and they are opaque, which means they are never
387 ! accessed or modified in WRF; they are only only passed between calls to
388 ! the external package.
393 LOGICAL, DIMENSION(4), INTENT(OUT) :: bdy_mask
394 INTEGER, INTENT(IN) :: sd1 , ed1 , sd2 , ed2 , sd3 , ed3 , bdx , bdy
395 INTEGER, INTENT(OUT) :: sp1 , ep1 , sp2 , ep2 , sp3 , ep3 , & ! z-xpose (std)
396 sm1 , em1 , sm2 , em2 , sm3 , em3
397 INTEGER, INTENT(OUT) :: sp1x , ep1x , sp2x , ep2x , sp3x , ep3x , & ! x-xpose
398 sm1x , em1x , sm2x , em2x , sm3x , em3x
399 INTEGER, INTENT(OUT) :: sp1y , ep1y , sp2y , ep2y , sp3y , ep3y , & ! y-xpose
400 sm1y , em1y , sm2y , em2y , sm3y , em3y
401 INTEGER, INTENT(IN) :: id , parent_id , parent_domdesc
402 INTEGER, INTENT(INOUT) :: domdesc
403 TYPE(domain), POINTER :: parent
407 INTEGER spec_bdy_width
409 CALL nl_get_spec_bdy_width( 1, spec_bdy_width )
413 bdy_mask = .true. ! only one processor so all 4 boundaries are there
415 ! this is a trivial version -- 1 patch per processor;
416 ! use version in module_dm to compute for DM
417 sp1 = sd1 ; sp2 = sd2 ; sp3 = sd3
418 ep1 = ed1 ; ep2 = ed2 ; ep3 = ed3
419 SELECT CASE ( model_data_order )
420 CASE ( DATA_ORDER_XYZ )
421 sm1 = sp1 - bdx ; em1 = ep1 + bdx
422 sm2 = sp2 - bdy ; em2 = ep2 + bdy
423 sm3 = sp3 ; em3 = ep3
424 CASE ( DATA_ORDER_YXZ )
425 sm1 = sp1 - bdy ; em1 = ep1 + bdy
426 sm2 = sp2 - bdx ; em2 = ep2 + bdx
427 sm3 = sp3 ; em3 = ep3
428 CASE ( DATA_ORDER_ZXY )
429 sm1 = sp1 ; em1 = ep1
430 sm2 = sp2 - bdx ; em2 = ep2 + bdx
431 sm3 = sp3 - bdy ; em3 = ep3 + bdy
432 CASE ( DATA_ORDER_ZYX )
433 sm1 = sp1 ; em1 = ep1
434 sm2 = sp2 - bdy ; em2 = ep2 + bdy
435 sm3 = sp3 - bdx ; em3 = ep3 + bdx
436 CASE ( DATA_ORDER_XZY )
437 sm1 = sp1 - bdx ; em1 = ep1 + bdx
438 sm2 = sp2 ; em2 = ep2
439 sm3 = sp3 - bdy ; em3 = ep3 + bdy
440 CASE ( DATA_ORDER_YZX )
441 sm1 = sp1 - bdy ; em1 = ep1 + bdy
442 sm2 = sp2 ; em2 = ep2
443 sm3 = sp3 - bdx ; em3 = ep3 + bdx
445 sm1x = sm1 ; em1x = em1 ! just copy
446 sm2x = sm2 ; em2x = em2
447 sm3x = sm3 ; em3x = em3
448 sm1y = sm1 ; em1y = em1 ! just copy
449 sm2y = sm2 ; em2y = em2
450 sm3y = sm3 ; em3y = em3
451 ! assigns mostly just to suppress warning messages that INTENT OUT vars not assigned
452 sp1x = sp1 ; ep1x = ep1 ; sp2x = sp2 ; ep2x = ep2 ; sp3x = sp3 ; ep3x = ep3
453 sp1y = sp1 ; ep1y = ep1 ; sp2y = sp2 ; ep2y = ep2 ; sp3y = sp3 ; ep3y = ep3
456 ! This is supplied by the package specific version of module_dm, which
457 ! is supplied by the external package and copied into the src directory
458 ! when the code is compiled. The cp command will be found in the externals
459 ! target of the configure.wrf file for this architecture. Eg: for RSL
460 ! routine is defined in external/RSL/module_dm.F .
461 ! Note, it would be very nice to be able to pass parent to this routine;
462 ! however, there doesn't seem to be a way to do that in F90. That is because
463 ! to pass a pointer to a domain structure, this call requires an interface
464 ! definition for wrf_dm_patch_domain (otherwise it will try to convert the
465 ! pointer to something). In order to provide an interface definition, we
466 ! would need to either USE module_dm or use an interface block. In either
467 ! case it generates a circular USE reference, since module_dm uses
468 ! module_domain. JM 20020416
470 CALL wrf_dm_patch_domain( id , domdesc , parent_id , parent_domdesc , &
471 sd1 , ed1 , sp1 , ep1 , sm1 , em1 , &
472 sd2 , ed2 , sp2 , ep2 , sm2 , em2 , &
473 sd3 , ed3 , sp3 , ep3 , sm3 , em3 , &
474 sp1x , ep1x , sm1x , em1x , &
475 sp2x , ep2x , sm2x , em2x , &
476 sp3x , ep3x , sm3x , em3x , &
477 sp1y , ep1y , sm1y , em1y , &
478 sp2y , ep2y , sm2y , em2y , &
479 sp3y , ep3y , sm3y , em3y , &
482 SELECT CASE ( model_data_order )
483 CASE ( DATA_ORDER_XYZ )
484 bdy_mask( P_XSB ) = ( sd1 <= sp1 .AND. sp1 <= sd1+spec_bdy_width-1 )
485 bdy_mask( P_YSB ) = ( sd2 <= sp2 .AND. sp2 <= sd2+spec_bdy_width-1 )
486 bdy_mask( P_XEB ) = ( ed1-spec_bdy_width-1 <= ep1 .AND. ep1 <= ed1 )
487 bdy_mask( P_YEB ) = ( ed2-spec_bdy_width-1 <= ep2 .AND. ep2 <= ed2 )
488 CASE ( DATA_ORDER_YXZ )
489 bdy_mask( P_XSB ) = ( sd2 <= sp2 .AND. sp2 <= sd2+spec_bdy_width-1 )
490 bdy_mask( P_YSB ) = ( sd1 <= sp1 .AND. sp1 <= sd1+spec_bdy_width-1 )
491 bdy_mask( P_XEB ) = ( ed2-spec_bdy_width-1 <= ep2 .AND. ep2 <= ed2 )
492 bdy_mask( P_YEB ) = ( ed1-spec_bdy_width-1 <= ep1 .AND. ep1 <= ed1 )
493 CASE ( DATA_ORDER_ZXY )
494 bdy_mask( P_XSB ) = ( sd2 <= sp2 .AND. sp2 <= sd2+spec_bdy_width-1 )
495 bdy_mask( P_YSB ) = ( sd3 <= sp3 .AND. sp3 <= sd3+spec_bdy_width-1 )
496 bdy_mask( P_XEB ) = ( ed2-spec_bdy_width-1 <= ep2 .AND. ep2 <= ed2 )
497 bdy_mask( P_YEB ) = ( ed3-spec_bdy_width-1 <= ep3 .AND. ep3 <= ed3 )
498 CASE ( DATA_ORDER_ZYX )
499 bdy_mask( P_XSB ) = ( sd3 <= sp3 .AND. sp3 <= sd3+spec_bdy_width-1 )
500 bdy_mask( P_YSB ) = ( sd2 <= sp2 .AND. sp2 <= sd2+spec_bdy_width-1 )
501 bdy_mask( P_XEB ) = ( ed3-spec_bdy_width-1 <= ep3 .AND. ep3 <= ed3 )
502 bdy_mask( P_YEB ) = ( ed2-spec_bdy_width-1 <= ep2 .AND. ep2 <= ed2 )
503 CASE ( DATA_ORDER_XZY )
504 bdy_mask( P_XSB ) = ( sd1 <= sp1 .AND. sp1 <= sd1+spec_bdy_width-1 )
505 bdy_mask( P_YSB ) = ( sd3 <= sp3 .AND. sp3 <= sd3+spec_bdy_width-1 )
506 bdy_mask( P_XEB ) = ( ed1-spec_bdy_width-1 <= ep1 .AND. ep1 <= ed1 )
507 bdy_mask( P_YEB ) = ( ed3-spec_bdy_width-1 <= ep3 .AND. ep3 <= ed3 )
508 CASE ( DATA_ORDER_YZX )
509 bdy_mask( P_XSB ) = ( sd3 <= sp3 .AND. sp3 <= sd3+spec_bdy_width-1 )
510 bdy_mask( P_YSB ) = ( sd1 <= sp1 .AND. sp1 <= sd1+spec_bdy_width-1 )
511 bdy_mask( P_XEB ) = ( ed3-spec_bdy_width-1 <= ep3 .AND. ep3 <= ed3 )
512 bdy_mask( P_YEB ) = ( ed1-spec_bdy_width-1 <= ep1 .AND. ep1 <= ed1 )
518 END SUBROUTINE wrf_patch_domain
520 SUBROUTINE alloc_and_configure_domain ( domain_id , active_this_task, grid , parent, kid )
523 ! This subroutine is used to allocate a domain data structure of
524 ! TYPE(DOMAIN) pointed to by the argument <em>grid</em>, link it into the
525 ! nested domain hierarchy, and set it's configuration information from
526 ! the appropriate settings in the WRF namelist file. Specifically, if the
527 ! domain being allocated and configured is nest, the <em>parent</em>
528 ! argument will point to the already existing domain data structure for
529 ! the parent domain and the <em>kid</em> argument will be set to an
530 ! integer indicating which child of the parent this grid will be (child
531 ! indices start at 1). If this is the top-level domain, the parent and
532 ! kid arguments are ignored. <b>WRF domains may have multiple children
533 ! but only ever have one parent.</b>
535 ! The <em>domain_id</em> argument is the
536 ! integer handle by which this new domain will be referred; it comes from
537 ! the grid_id setting in the namelist, and these grid ids correspond to
538 ! the ordering of settings in the namelist, starting with 1 for the
539 ! top-level domain. The id of 1 always corresponds to the top-level
540 ! domain. and these grid ids correspond to the ordering of settings in
541 ! the namelist, starting with 1 for the top-level domain.
543 ! Model_data_order is provide by USE association of
544 ! module_driver_constants and is set from dimspec entries in the
547 ! The allocation of the TYPE(DOMAIN) itself occurs in this routine.
548 ! However, the numerous multi-dimensional arrays that make up the members
549 ! of the domain are allocated in the call to alloc_space_field, after
550 ! wrf_patch_domain has been called to determine the dimensions in memory
551 ! that should be allocated. It bears noting here that arrays and code
552 ! that indexes these arrays are always global, regardless of how the
553 ! model is decomposed over patches. Thus, when arrays are allocated on a
554 ! given process, the start and end of an array dimension are the global
555 ! indices of the start and end of that process's subdomain.
557 ! Configuration information for the domain (that is, information from the
558 ! namelist) is added by the call to <a href=med_add_config_info_to_grid.html>med_add_config_info_to_grid</a>, defined
559 ! in share/mediation_wrfmain.F.
566 INTEGER , INTENT(IN) :: domain_id
567 LOGICAL , OPTIONAL, INTENT(IN) :: active_this_task ! false if domain is being handled by other MPI tasks
568 TYPE( domain ) , POINTER :: grid
569 TYPE( domain ) , POINTER :: parent
570 INTEGER , INTENT(IN) :: kid ! which kid of parent am I?
573 INTEGER :: sd1 , ed1 , sp1 , ep1 , sm1 , em1
574 INTEGER :: sd2 , ed2 , sp2 , ep2 , sm2 , em2
575 INTEGER :: sd3 , ed3 , sp3 , ep3 , sm3 , em3
577 INTEGER :: sd1x , ed1x , sp1x , ep1x , sm1x , em1x
578 INTEGER :: sd2x , ed2x , sp2x , ep2x , sm2x , em2x
579 INTEGER :: sd3x , ed3x , sp3x , ep3x , sm3x , em3x
581 INTEGER :: sd1y , ed1y , sp1y , ep1y , sm1y , em1y
582 INTEGER :: sd2y , ed2y , sp2y , ep2y , sm2y , em2y
583 INTEGER :: sd3y , ed3y , sp3y , ep3y , sm3y , em3y
585 TYPE(domain) , POINTER :: new_grid
587 INTEGER :: parent_id , parent_domdesc , new_domdesc
588 INTEGER :: bdyzone_x , bdyzone_y
594 IF ( PRESENT( active_this_task ) ) THEN
595 active = active_this_task
598 ! This next step uses information that is listed in the registry as namelist_derived
599 ! to properly size the domain and the patches; this in turn is stored in the new_grid
603 data_ordering : SELECT CASE ( model_data_order )
604 CASE ( DATA_ORDER_XYZ )
606 CALL nl_get_s_we( domain_id , sd1 )
607 CALL nl_get_e_we( domain_id , ed1 )
608 CALL nl_get_s_sn( domain_id , sd2 )
609 CALL nl_get_e_sn( domain_id , ed2 )
610 CALL nl_get_s_vert( domain_id , sd3 )
611 CALL nl_get_e_vert( domain_id , ed3 )
615 CASE ( DATA_ORDER_YXZ )
617 CALL nl_get_s_sn( domain_id , sd1 )
618 CALL nl_get_e_sn( domain_id , ed1 )
619 CALL nl_get_s_we( domain_id , sd2 )
620 CALL nl_get_e_we( domain_id , ed2 )
621 CALL nl_get_s_vert( domain_id , sd3 )
622 CALL nl_get_e_vert( domain_id , ed3 )
626 CASE ( DATA_ORDER_ZXY )
628 CALL nl_get_s_vert( domain_id , sd1 )
629 CALL nl_get_e_vert( domain_id , ed1 )
630 CALL nl_get_s_we( domain_id , sd2 )
631 CALL nl_get_e_we( domain_id , ed2 )
632 CALL nl_get_s_sn( domain_id , sd3 )
633 CALL nl_get_e_sn( domain_id , ed3 )
637 CASE ( DATA_ORDER_ZYX )
639 CALL nl_get_s_vert( domain_id , sd1 )
640 CALL nl_get_e_vert( domain_id , ed1 )
641 CALL nl_get_s_sn( domain_id , sd2 )
642 CALL nl_get_e_sn( domain_id , ed2 )
643 CALL nl_get_s_we( domain_id , sd3 )
644 CALL nl_get_e_we( domain_id , ed3 )
648 CASE ( DATA_ORDER_XZY )
650 CALL nl_get_s_we( domain_id , sd1 )
651 CALL nl_get_e_we( domain_id , ed1 )
652 CALL nl_get_s_vert( domain_id , sd2 )
653 CALL nl_get_e_vert( domain_id , ed2 )
654 CALL nl_get_s_sn( domain_id , sd3 )
655 CALL nl_get_e_sn( domain_id , ed3 )
659 CASE ( DATA_ORDER_YZX )
661 CALL nl_get_s_sn( domain_id , sd1 )
662 CALL nl_get_e_sn( domain_id , ed1 )
663 CALL nl_get_s_vert( domain_id , sd2 )
664 CALL nl_get_e_vert( domain_id , ed2 )
665 CALL nl_get_s_we( domain_id , sd3 )
666 CALL nl_get_e_we( domain_id , ed3 )
670 END SELECT data_ordering
672 IF ( num_time_levels > 3 ) THEN
673 WRITE ( wrf_err_message , * ) 'alloc_and_configure_domain: ', &
674 'Incorrect value for num_time_levels ', num_time_levels
675 CALL wrf_error_fatal ( TRIM ( wrf_err_message ) )
678 IF (ASSOCIATED(parent)) THEN
679 parent_id = parent%id
680 parent_domdesc = parent%domdesc
686 ! provided by application, WRF defines in share/module_bc.F
687 CALL get_bdyzone_x( bdyzone_x )
688 CALL get_bdyzone_y( bdyzone_y )
690 ALLOCATE ( new_grid )
691 ALLOCATE( new_grid%head_statevars )
692 new_grid%head_statevars%Ndim = 0
693 NULLIFY( new_grid%head_statevars%next)
694 new_grid%tail_statevars => new_grid%head_statevars
696 ALLOCATE ( new_grid%parents( max_parents ) )
697 ALLOCATE ( new_grid%nests( max_nests ) )
698 NULLIFY( new_grid%sibling )
700 NULLIFY( new_grid%nests(i)%ptr )
702 NULLIFY (new_grid%next)
703 NULLIFY (new_grid%same_level)
704 NULLIFY (new_grid%i_start)
705 NULLIFY (new_grid%j_start)
706 NULLIFY (new_grid%i_end)
707 NULLIFY (new_grid%j_end)
708 ALLOCATE( new_grid%domain_clock )
709 new_grid%domain_clock_created = .FALSE.
710 ALLOCATE( new_grid%alarms( MAX_WRF_ALARMS ) ) ! initialize in setup_timekeeping
711 ALLOCATE( new_grid%alarms_created( MAX_WRF_ALARMS ) )
712 DO i = 1, MAX_WRF_ALARMS
713 new_grid%alarms_created( i ) = .FALSE.
715 new_grid%time_set = .FALSE.
716 new_grid%is_intermediate = .FALSE.
717 new_grid%have_displayed_alloc_stats = .FALSE.
719 new_grid%tiling_latch = .FALSE. ! 20121003
721 ! set up the pointers that represent the nest hierarchy
722 ! set this up *prior* to calling the patching or allocation
723 ! routines so that implementations of these routines can
724 ! traverse the nest hierarchy (through the root head_grid)
728 IF ( domain_id .NE. 1 ) THEN
729 new_grid%parents(1)%ptr => parent
730 new_grid%num_parents = 1
731 parent%nests(kid)%ptr => new_grid
732 new_grid%child_of_parent(1) = kid ! note assumption that nest can have only 1 parent
733 parent%num_nests = parent%num_nests + 1
735 new_grid%id = domain_id ! this needs to be assigned prior to calling wrf_patch_domain
736 new_grid%active_this_task = active
738 CALL wrf_patch_domain( domain_id , new_domdesc , parent, parent_id, parent_domdesc , &
740 sd1 , ed1 , sp1 , ep1 , sm1 , em1 , & ! z-xpose dims
741 sd2 , ed2 , sp2 , ep2 , sm2 , em2 , & ! (standard)
742 sd3 , ed3 , sp3 , ep3 , sm3 , em3 , &
744 sp1x , ep1x , sm1x , em1x , & ! x-xpose dims
745 sp2x , ep2x , sm2x , em2x , &
746 sp3x , ep3x , sm3x , em3x , &
748 sp1y , ep1y , sm1y , em1y , & ! y-xpose dims
749 sp2y , ep2y , sm2y , em2y , &
750 sp3y , ep3y , sm3y , em3y , &
752 bdyzone_x , bdyzone_y , new_grid%bdy_mask &
756 new_grid%domdesc = new_domdesc
757 new_grid%num_nests = 0
758 new_grid%num_siblings = 0
759 new_grid%num_parents = 0
760 new_grid%max_tiles = 0
761 new_grid%num_tiles_spec = 0
762 new_grid%nframes = 0 ! initialize the number of frames per file (array assignment)
765 ! new_grid%stepping_to_time = .FALSE.
766 ! new_grid%adaptation_domain = 1
767 ! new_grid%last_step_updated = -1
772 ! only allocate state if this set of tasks actually computes that domain, jm 20140822
773 new_grid%active_this_task = active
774 CALL alloc_space_field ( new_grid, domain_id , 3 , 3 , .FALSE. , active, &
775 sd1, ed1, sd2, ed2, sd3, ed3, &
776 sm1, em1, sm2, em2, sm3, em3, &
777 sp1, ep1, sp2, ep2, sp3, ep3, &
778 sp1x, ep1x, sp2x, ep2x, sp3x, ep3x, &
779 sp1y, ep1y, sp2y, ep2y, sp3y, ep3y, &
780 sm1x, em1x, sm2x, em2x, sm3x, em3x, & ! x-xpose
781 sm1y, em1y, sm2y, em2y, sm3y, em3y & ! y-xpose
784 ! WRITE (wrf_err_message,*)"Not allocating storage for domain ",domain_id," on this set of tasks"
785 ! CALL wrf_message(TRIM(wrf_err_message))
790 !Set these here, after alloc_space_field, which initializes at least last_step_updated to zero
791 new_grid%stepping_to_time = .FALSE.
792 new_grid%adaptation_domain = 1
793 new_grid%last_step_updated = -1
798 !set these here, after alloc_space_field, which initializes vc_i, vc_j to zero
824 new_grid%sp31x = sp1x
825 new_grid%ep31x = ep1x
826 new_grid%sm31x = sm1x
827 new_grid%em31x = em1x
828 new_grid%sp32x = sp2x
829 new_grid%ep32x = ep2x
830 new_grid%sm32x = sm2x
831 new_grid%em32x = em2x
832 new_grid%sp33x = sp3x
833 new_grid%ep33x = ep3x
834 new_grid%sm33x = sm3x
835 new_grid%em33x = em3x
837 new_grid%sp31y = sp1y
838 new_grid%ep31y = ep1y
839 new_grid%sm31y = sm1y
840 new_grid%em31y = em1y
841 new_grid%sp32y = sp2y
842 new_grid%ep32y = ep2y
843 new_grid%sm32y = sm2y
844 new_grid%em32y = em2y
845 new_grid%sp33y = sp3y
846 new_grid%ep33y = ep3y
847 new_grid%sm33y = sm3y
848 new_grid%em33y = em3y
850 SELECT CASE ( model_data_order )
851 CASE ( DATA_ORDER_XYZ )
852 new_grid%sd21 = sd1 ; new_grid%sd22 = sd2 ;
853 new_grid%ed21 = ed1 ; new_grid%ed22 = ed2 ;
854 new_grid%sp21 = sp1 ; new_grid%sp22 = sp2 ;
855 new_grid%ep21 = ep1 ; new_grid%ep22 = ep2 ;
856 new_grid%sm21 = sm1 ; new_grid%sm22 = sm2 ;
857 new_grid%em21 = em1 ; new_grid%em22 = em2 ;
864 CASE ( DATA_ORDER_YXZ )
865 new_grid%sd21 = sd1 ; new_grid%sd22 = sd2 ;
866 new_grid%ed21 = ed1 ; new_grid%ed22 = ed2 ;
867 new_grid%sp21 = sp1 ; new_grid%sp22 = sp2 ;
868 new_grid%ep21 = ep1 ; new_grid%ep22 = ep2 ;
869 new_grid%sm21 = sm1 ; new_grid%sm22 = sm2 ;
870 new_grid%em21 = em1 ; new_grid%em22 = em2 ;
877 CASE ( DATA_ORDER_ZXY )
878 new_grid%sd21 = sd2 ; new_grid%sd22 = sd3 ;
879 new_grid%ed21 = ed2 ; new_grid%ed22 = ed3 ;
880 new_grid%sp21 = sp2 ; new_grid%sp22 = sp3 ;
881 new_grid%ep21 = ep2 ; new_grid%ep22 = ep3 ;
882 new_grid%sm21 = sm2 ; new_grid%sm22 = sm3 ;
883 new_grid%em21 = em2 ; new_grid%em22 = em3 ;
890 CASE ( DATA_ORDER_ZYX )
891 new_grid%sd21 = sd2 ; new_grid%sd22 = sd3 ;
892 new_grid%ed21 = ed2 ; new_grid%ed22 = ed3 ;
893 new_grid%sp21 = sp2 ; new_grid%sp22 = sp3 ;
894 new_grid%ep21 = ep2 ; new_grid%ep22 = ep3 ;
895 new_grid%sm21 = sm2 ; new_grid%sm22 = sm3 ;
896 new_grid%em21 = em2 ; new_grid%em22 = em3 ;
903 CASE ( DATA_ORDER_XZY )
904 new_grid%sd21 = sd1 ; new_grid%sd22 = sd3 ;
905 new_grid%ed21 = ed1 ; new_grid%ed22 = ed3 ;
906 new_grid%sp21 = sp1 ; new_grid%sp22 = sp3 ;
907 new_grid%ep21 = ep1 ; new_grid%ep22 = ep3 ;
908 new_grid%sm21 = sm1 ; new_grid%sm22 = sm3 ;
909 new_grid%em21 = em1 ; new_grid%em22 = em3 ;
916 CASE ( DATA_ORDER_YZX )
917 new_grid%sd21 = sd1 ; new_grid%sd22 = sd3 ;
918 new_grid%ed21 = ed1 ; new_grid%ed22 = ed3 ;
919 new_grid%sp21 = sp1 ; new_grid%sp22 = sp3 ;
920 new_grid%ep21 = ep1 ; new_grid%ep22 = ep3 ;
921 new_grid%sm21 = sm1 ; new_grid%sm22 = sm3 ;
922 new_grid%em21 = em1 ; new_grid%em22 = em3 ;
931 CALL med_add_config_info_to_grid ( new_grid ) ! this is a mediation layer routine
933 ! Some miscellaneous state that is in the Registry but not namelist data
935 new_grid%tiled = .false.
936 new_grid%patched = .false.
937 NULLIFY(new_grid%mapping)
939 ! This next set of includes causes all but the namelist_derived variables to be
940 ! properly assigned to the new_grid record
943 !debug write(0,*)__FILE__,__LINE__,'grid%mvnest ',grid%mvnest
945 !debug write(0,*)__FILE__,__LINE__,'grid%mvnest ',grid%mvnest
946 IF ( grid%active_this_task ) THEN
947 ! Allocate storage for time series metadata
948 ALLOCATE( grid%lattsloc( grid%max_ts_locs ) )
949 ALLOCATE( grid%lontsloc( grid%max_ts_locs ) )
950 ALLOCATE( grid%nametsloc( grid%max_ts_locs ) )
951 ALLOCATE( grid%desctsloc( grid%max_ts_locs ) )
952 ALLOCATE( grid%itsloc( grid%max_ts_locs ) )
953 ALLOCATE( grid%jtsloc( grid%max_ts_locs ) )
954 ALLOCATE( grid%id_tsloc( grid%max_ts_locs ) )
955 ALLOCATE( grid%ts_filename( grid%max_ts_locs ) )
957 grid%ntsloc_domain = 0
960 ! Allocate storage for track metadata
961 ALLOCATE( grid%track_time_in( grid%track_loc_in ) )
962 ALLOCATE( grid%track_lat_in( grid%track_loc_in ) )
963 ALLOCATE( grid%track_lon_in( grid%track_loc_in ) )
965 ALLOCATE( grid%track_time_domain( grid%track_loc_in ) )
966 ALLOCATE( grid%track_lat_domain( grid%track_loc_in ) )
967 ALLOCATE( grid%track_lon_domain( grid%track_loc_in ) )
968 ALLOCATE( grid%track_i( grid%track_loc_in ) )
969 ALLOCATE( grid%track_j( grid%track_loc_in ) )
972 grid%track_loc_domain = 0
973 grid%track_have_calculated = .FALSE.
974 grid%track_have_input = .FALSE.
977 WRITE (wrf_err_message,*)"Not allocating time series storage for domain ",domain_id," on this set of tasks"
978 CALL wrf_message(TRIM(wrf_err_message))
980 !debug write(0,*)__FILE__,__LINE__,'grid%mvnest ',grid%mvnest
982 CALL wrf_get_dm_communicator_for_id( grid%id, grid%communicator )
983 CALL wrf_dm_define_comms( grid )
986 grid%interp_mp = .true.
988 END SUBROUTINE alloc_and_configure_domain
990 SUBROUTINE get_fieldstr(ix,c,instr,outstr,noutstr,noerr)
992 INTEGER, INTENT(IN) :: ix
993 CHARACTER*(*), INTENT(IN) :: c
994 CHARACTER*(*), INTENT(IN) :: instr
995 CHARACTER*(*), INTENT(OUT) :: outstr
996 INTEGER, INTENT(IN) :: noutstr ! length of outstr
997 LOGICAL, INTENT(INOUT) :: noerr ! status
999 INTEGER, PARAMETER :: MAX_DEXES = 1000
1000 INTEGER I, PREV, IDEX
1001 INTEGER DEXES(MAX_DEXES)
1006 idex = INDEX(instr(prev:LEN(TRIM(instr))),c)
1007 IF ( idex .GT. 0 ) THEN
1008 dexes(i) = idex+prev
1011 dexes(i) = LEN(TRIM(instr))+2
1015 IF ( (dexes(ix+1)-2)-(dexes(ix)) .GT. noutstr ) THEN
1016 noerr = .FALSE. ! would overwrite
1017 ELSE IF( dexes(ix) .EQ. dexes(ix+1) ) THEN
1018 noerr = .FALSE. ! not found
1020 outstr = instr(dexes(ix):(dexes(ix+1)-2))
1021 noerr = noerr .AND. .TRUE.
1023 END SUBROUTINE get_fieldstr
1025 SUBROUTINE change_to_lower_case(instr,outstr)
1026 CHARACTER*(*) ,INTENT(IN) :: instr
1027 CHARACTER*(*) ,INTENT(OUT) :: outstr
1030 INTEGER ,PARAMETER :: upper_to_lower =IACHAR('a')-IACHAR('A')
1037 outstr(1:N) = instr(1:N)
1040 if('A'<=c .and. c <='Z') outstr(i:i)=achar(iachar(c)+upper_to_lower)
1043 END SUBROUTINE change_to_lower_case
1046 SUBROUTINE modify_io_masks1 ( grid , id )
1048 #include "streams.h"
1049 INTEGER , INTENT(IN ) :: id
1050 TYPE(domain), POINTER :: grid
1052 TYPE(fieldlist), POINTER :: p, q
1053 INTEGER, PARAMETER :: read_unit = 10
1054 LOGICAL, EXTERNAL :: wrf_dm_on_monitor
1055 CHARACTER*8000 :: inln, t1, fieldlst
1056 CHARACTER*256 :: fname, mess, dname, lookee
1057 CHARACTER*1 :: op, strmtyp
1058 CHARACTER*3 :: strmid
1059 CHARACTER*10 :: strmtyp_name
1060 INTEGER :: io_status
1061 INTEGER :: strmtyp_int, count_em
1062 INTEGER :: lineno, fieldno, istrm, retval, itrace
1063 LOGICAL :: keepgoing, noerr, gavewarning, ignorewarning, found
1064 LOGICAL, SAVE :: you_warned_me = .FALSE.
1065 LOGICAL, SAVE :: you_warned_me2(max_hst_mods,max_domains) = .FALSE.
1067 gavewarning = .FALSE.
1069 CALL nl_get_iofields_filename( id, fname )
1071 IF ( grid%is_intermediate ) RETURN ! short circuit
1072 IF ( TRIM(fname) .EQ. "NONE_SPECIFIED" ) RETURN ! short circuit
1074 IF ( wrf_dm_on_monitor() ) THEN
1075 OPEN ( UNIT = read_unit , &
1076 FILE = TRIM(fname) , &
1077 FORM = "FORMATTED" , &
1079 IOSTAT = io_status )
1080 IF ( io_status .EQ. 0 ) THEN ! only on success
1083 count_em = 0 ! Count the total number of fields
1084 DO WHILE ( keepgoing )
1085 READ(UNIT=read_unit,FMT='(A)',IOSTAT=io_status) inln
1086 keepgoing = (io_status .EQ. 0) .AND. (LEN(TRIM(inln)) .GT. 0)
1087 IF ( keepgoing ) THEN
1089 IF ( .NOT. LEN(TRIM(inln)) .LT. LEN(inln) ) THEN
1090 WRITE(mess,*)'W A R N I N G : Line ',lineno,' of ',TRIM(fname),' is too long. Limit is ',LEN(inln),' characters.'
1091 gavewarning = .TRUE.
1093 IF ( INDEX(inln,'#') .EQ. 0 ) THEN ! skip comments, which is a # anywhere on line
1094 IF ( keepgoing ) THEN
1096 CALL get_fieldstr(1,':',inln,op,1,noerr) ! + is add, - is remove
1097 IF ( TRIM(op) .NE. '+' .AND. TRIM(op) .NE. '-' ) THEN
1098 WRITE(mess,*)'W A R N I N G : unknown operation ',TRIM(op),' (should be + or -). Line ',lineno
1099 gavewarning = .TRUE.
1101 CALL get_fieldstr(2,':',inln,t1,1,noerr) ! i is input, h is history
1102 CALL change_to_lower_case(t1,strmtyp)
1104 SELECT CASE (TRIM(strmtyp))
1106 strmtyp_name = 'history'
1107 strmtyp_int = first_history
1109 strmtyp_name = 'input'
1110 strmtyp_int = first_input
1112 WRITE(mess,*)'W A R N I N G : unknown stream type ',TRIM(strmtyp),'. Line ',lineno
1113 gavewarning = .TRUE.
1116 CALL get_fieldstr(3,':',inln,strmid,3,noerr) ! number of stream (main input and hist are 0)
1117 READ(strmid,'(I3)') istrm
1118 IF ( istrm .LT. 0 .OR. istrm .GT. last_history ) THEN
1119 WRITE(mess,*)'W A R N I N G : invalid stream id ',istrm,' (should be 0 <= id <= ',last_history,'). Line ',lineno
1120 gavewarning = .TRUE.
1122 CALL get_fieldstr(4,':',inln,fieldlst,8000,noerr) ! get list of fields
1125 CALL get_fieldstr(fieldno,',',fieldlst,t1,8000,noerr)
1126 CALL change_to_lower_case(t1,lookee)
1127 DO WHILE ( noerr ) ! linear search, blargh...
1128 p => grid%head_statevars%next
1130 count_em = count_em + 1
1131 DO WHILE ( ASSOCIATED( p ) )
1133 IF ( p%Ndim .EQ. 4 .AND. p%scalar_array ) THEN
1135 DO itrace = PARAM_FIRST_SCALAR , p%num_table(grid%id)
1136 CALL change_to_lower_case( p%dname_table( grid%id, itrace ) , dname )
1138 IF ( TRIM(dname) .EQ. TRIM(lookee) ) &
1139 CALL warn_me_or_set_mask (id, istrm, lineno, strmtyp_int, count_em, op, &
1140 strmtyp_name, dname, fname, lookee, &
1141 p%streams_table(grid%id,itrace)%stream, &
1142 mess, found, you_warned_me2)
1145 IF ( p%Ntl .GT. 0 ) THEN
1146 CALL change_to_lower_case(p%DataName(1:LEN(TRIM(p%DataName))-2),dname)
1148 CALL change_to_lower_case(p%DataName,dname)
1151 IF ( TRIM(dname) .EQ. TRIM(lookee) ) &
1152 CALL warn_me_or_set_mask (id, istrm, lineno, strmtyp_int, count_em, op, &
1153 strmtyp_name, dname, fname, lookee, &
1154 p%streams, mess, found, you_warned_me2)
1158 IF ( .NOT. found ) THEN
1159 #if ( WRFPLUS != 1 )
1160 WRITE(mess,*)'W A R N I N G : Unable to modify mask for ',TRIM(lookee),&
1161 '. Variable not found. File: ',TRIM(fname),' at line ',lineno
1162 CALL wrf_message(mess)
1164 gavewarning = .TRUE.
1166 fieldno = fieldno + 1
1167 CALL get_fieldstr(fieldno,',',fieldlst,t1,256,noerr)
1168 CALL change_to_lower_case(t1,lookee)
1171 WRITE(mess,*)'W A R N I N G : Problem reading ',TRIM(fname),' at line ',lineno
1172 CALL wrf_message(mess)
1173 gavewarning = .TRUE.
1176 ENDIF ! skip comments
1180 WRITE(mess,*)'W A R N I N G : Problem opening ',TRIM(fname)
1181 CALL wrf_message(mess)
1182 gavewarning = .TRUE.
1185 IF ( gavewarning ) THEN
1186 CALL nl_get_ignore_iofields_warning(1,ignorewarning)
1187 IF ( .NOT. ignorewarning ) THEN
1188 CALL wrf_message(mess)
1189 WRITE(mess,*)'modify_io_masks: problems reading ',TRIM(fname)
1190 CALL wrf_message(mess)
1191 CALL wrf_error_fatal('Set ignore_iofields_warn to true in namelist to ignore')
1193 IF ( .NOT. you_warned_me ) THEN
1194 if ( .NOT. you_warned_me2(count_em,id) ) CALL wrf_message(mess) ! Don't repeat the W A R N I N G message
1195 WRITE(mess,*)'Ignoring problems reading ',TRIM(fname)
1196 CALL wrf_message(mess)
1197 CALL wrf_message('Continuing. To make this a fatal error, set ignore_iofields_warn to false in namelist' )
1198 CALL wrf_message(' ')
1199 you_warned_me = .TRUE.
1203 ENDIF ! wrf_dm_on_monitor
1206 ! broadcast the new masks to the other tasks
1207 p => grid%head_statevars%next
1208 DO WHILE ( ASSOCIATED( p ) )
1209 IF ( p%Ndim .EQ. 4 .AND. p%scalar_array ) THEN
1211 DO itrace = PARAM_FIRST_SCALAR , p%num_table(grid%id)
1212 CALL wrf_dm_bcast_integer( p%streams_table(grid%id,itrace)%stream, IO_MASK_SIZE )
1216 CALL wrf_dm_bcast_integer( p%streams, IO_MASK_SIZE )
1222 END SUBROUTINE modify_io_masks1
1224 SUBROUTINE warn_me_or_set_mask (id, istrm, lineno, strmtyp_int, count_em, op, &
1225 strmtyp_name, dname, fname, lookee, &
1226 p_stream, mess, found, you_warned_me2)
1230 ! See if a field that is requested to be added to or removed from the I/O stream
1231 ! is already present or absent
1232 ! If the requested action has already been done, write a warning message
1233 ! If not, satisfy the request
1235 INTEGER, INTENT(IN ) :: id, istrm, lineno, strmtyp_int
1236 INTEGER, INTENT(IN ) :: p_stream(*), count_em
1237 CHARACTER*1, INTENT(IN ) :: op
1238 CHARACTER*10, INTENT(IN ) :: strmtyp_name
1239 CHARACTER*256, INTENT(IN ) :: dname, fname, lookee
1240 CHARACTER*256, INTENT(OUT) :: mess
1241 LOGICAL, INTENT(OUT) :: found
1242 LOGICAL, INTENT(INOUT) :: you_warned_me2(max_hst_mods,max_domains)
1247 IF ( TRIM(op) .EQ. '+' ) THEN
1248 CALL get_mask( p_stream, strmtyp_int + istrm - 1, retval )
1249 IF ( retval .NE. 0 ) THEN
1250 WRITE(mess,*) 'Domain ',id, ' W A R N I N G : Variable ',TRIM(lookee),' already on ', &
1251 TRIM(strmtyp_name), ' stream ',istrm, '. File: ', TRIM(fname),' at line ',lineno
1253 WRITE(mess,*) 'Domain ', id, ' Setting ', TRIM(strmtyp_name), ' stream ',istrm,' for ', &
1254 TRIM(DNAME) ; CALL wrf_debug(1,mess)
1255 CALL set_mask( p_stream, strmtyp_int + istrm - 1 )
1257 ELSE IF ( TRIM(op) .EQ. '-' ) THEN
1258 CALL get_mask( p_stream, strmtyp_int + istrm - 1, retval )
1259 IF ( retval .EQ. 0 ) THEN
1260 WRITE(mess,*) 'Domain ',id, ' W A R N I N G : Variable ',TRIM(lookee),' already off ', &
1261 TRIM(strmtyp_name), ' stream ',istrm, '. File: ',TRIM(fname),' at line ',lineno
1263 WRITE(mess,*) 'Domain ', id, ' Resetting ', TRIM(strmtyp_name), ' stream ',istrm,' for ', &
1264 TRIM(DNAME) ; CALL wrf_debug(1,mess)
1265 CALL reset_mask( p_stream, strmtyp_int + istrm - 1)
1268 IF ( count_em > max_hst_mods ) THEN
1269 #if ( DA_CORE != 1 )
1270 WRITE(mess,*)'ERROR module_domain: Array size for you_warned_me2 is fixed at ',max_hst_mods
1271 CALL wrf_message(mess)
1272 CALL wrf_error_fatal('Did you really type > max_hst_mods fields into ', TRIM(fname) ,' ?')
1275 IF ( .NOT. you_warned_me2(count_em,id) ) THEN
1276 CALL wrf_message(mess) ! Write warning message once for each field
1277 you_warned_me2(count_em,id) = .TRUE.
1281 END SUBROUTINE warn_me_or_set_mask
1283 ! This routine ALLOCATEs the required space for the meteorological fields
1284 ! for a specific domain. The fields are simply ALLOCATEd as an -1. They
1285 ! are referenced as wind, temperature, moisture, etc. in routines that are
1286 ! below this top-level of data allocation and management (in the solve routine
1289 SUBROUTINE alloc_space_field ( grid, id, setinitval_in , tl_in , inter_domain_in , okay_to_alloc_in, &
1290 sd31, ed31, sd32, ed32, sd33, ed33, &
1291 sm31 , em31 , sm32 , em32 , sm33 , em33 , &
1292 sp31 , ep31 , sp32 , ep32 , sp33 , ep33 , &
1293 sp31x, ep31x, sp32x, ep32x, sp33x, ep33x, &
1294 sp31y, ep31y, sp32y, ep32y, sp33y, ep33y, &
1295 sm31x, em31x, sm32x, em32x, sm33x, em33x, &
1296 sm31y, em31y, sm32y, em32y, sm33y, em33y )
1298 USE module_alloc_space_0, ONLY : alloc_space_field_core_0
1299 USE module_alloc_space_1, ONLY : alloc_space_field_core_1
1300 USE module_alloc_space_2, ONLY : alloc_space_field_core_2
1301 USE module_alloc_space_3, ONLY : alloc_space_field_core_3
1302 USE module_alloc_space_4, ONLY : alloc_space_field_core_4
1303 USE module_alloc_space_5, ONLY : alloc_space_field_core_5
1304 USE module_alloc_space_6, ONLY : alloc_space_field_core_6
1305 USE module_alloc_space_7, ONLY : alloc_space_field_core_7
1306 USE module_alloc_space_8, ONLY : alloc_space_field_core_8
1307 USE module_alloc_space_9, ONLY : alloc_space_field_core_9
1313 TYPE(domain) , POINTER :: grid
1314 INTEGER , INTENT(IN) :: id
1315 INTEGER , INTENT(IN) :: setinitval_in ! 3 = everything, 1 = arrays only, 0 = none
1316 INTEGER , INTENT(IN) :: sd31, ed31, sd32, ed32, sd33, ed33
1317 INTEGER , INTENT(IN) :: sm31, em31, sm32, em32, sm33, em33
1318 INTEGER , INTENT(IN) :: sp31, ep31, sp32, ep32, sp33, ep33
1319 INTEGER , INTENT(IN) :: sp31x, ep31x, sp32x, ep32x, sp33x, ep33x
1320 INTEGER , INTENT(IN) :: sp31y, ep31y, sp32y, ep32y, sp33y, ep33y
1321 INTEGER , INTENT(IN) :: sm31x, em31x, sm32x, em32x, sm33x, em33x
1322 INTEGER , INTENT(IN) :: sm31y, em31y, sm32y, em32y, sm33y, em33y
1324 ! this argument is a bitmask. First bit is time level 1, second is time level 2, and so on.
1325 ! e.g. to set both 1st and second time level, use 3
1326 ! to set only 1st use 1
1327 ! to set only 2st use 2
1328 INTEGER , INTENT(IN) :: tl_in
1330 ! true if the allocation is for an intermediate domain (for nesting); only certain fields allocated
1331 ! false otherwise (all allocated, modulo tl above)
1332 LOGICAL , INTENT(IN) :: inter_domain_in, okay_to_alloc_in
1335 INTEGER(KIND=8) num_bytes_allocated
1336 INTEGER idum1, idum2
1339 IF ( grid%id .EQ. 1 ) CALL wrf_message ( &
1340 'DYNAMICS OPTION: Eulerian Mass Coordinate ')
1343 CALL set_scalar_indices_from_config( id , idum1 , idum2 )
1345 num_bytes_allocated = 0
1347 ! now separate modules to reduce the size of module_domain that the compiler sees
1348 CALL alloc_space_field_core_0 ( grid, id, setinitval_in , tl_in , inter_domain_in , okay_to_alloc_in, num_bytes_allocated , &
1349 sd31, ed31, sd32, ed32, sd33, ed33, &
1350 sm31 , em31 , sm32 , em32 , sm33 , em33 , &
1351 sp31 , ep31 , sp32 , ep32 , sp33 , ep33 , &
1352 sp31x, ep31x, sp32x, ep32x, sp33x, ep33x, &
1353 sp31y, ep31y, sp32y, ep32y, sp33y, ep33y, &
1354 sm31x, em31x, sm32x, em32x, sm33x, em33x, &
1355 sm31y, em31y, sm32y, em32y, sm33y, em33y )
1356 CALL alloc_space_field_core_1 ( grid, id, setinitval_in , tl_in , inter_domain_in , okay_to_alloc_in, num_bytes_allocated , &
1357 sd31, ed31, sd32, ed32, sd33, ed33, &
1358 sm31 , em31 , sm32 , em32 , sm33 , em33 , &
1359 sp31 , ep31 , sp32 , ep32 , sp33 , ep33 , &
1360 sp31x, ep31x, sp32x, ep32x, sp33x, ep33x, &
1361 sp31y, ep31y, sp32y, ep32y, sp33y, ep33y, &
1362 sm31x, em31x, sm32x, em32x, sm33x, em33x, &
1363 sm31y, em31y, sm32y, em32y, sm33y, em33y )
1364 CALL alloc_space_field_core_2 ( grid, id, setinitval_in , tl_in , inter_domain_in , okay_to_alloc_in, num_bytes_allocated , &
1365 sd31, ed31, sd32, ed32, sd33, ed33, &
1366 sm31 , em31 , sm32 , em32 , sm33 , em33 , &
1367 sp31 , ep31 , sp32 , ep32 , sp33 , ep33 , &
1368 sp31x, ep31x, sp32x, ep32x, sp33x, ep33x, &
1369 sp31y, ep31y, sp32y, ep32y, sp33y, ep33y, &
1370 sm31x, em31x, sm32x, em32x, sm33x, em33x, &
1371 sm31y, em31y, sm32y, em32y, sm33y, em33y )
1372 CALL alloc_space_field_core_3 ( grid, id, setinitval_in , tl_in , inter_domain_in , okay_to_alloc_in, num_bytes_allocated , &
1373 sd31, ed31, sd32, ed32, sd33, ed33, &
1374 sm31 , em31 , sm32 , em32 , sm33 , em33 , &
1375 sp31 , ep31 , sp32 , ep32 , sp33 , ep33 , &
1376 sp31x, ep31x, sp32x, ep32x, sp33x, ep33x, &
1377 sp31y, ep31y, sp32y, ep32y, sp33y, ep33y, &
1378 sm31x, em31x, sm32x, em32x, sm33x, em33x, &
1379 sm31y, em31y, sm32y, em32y, sm33y, em33y )
1380 CALL alloc_space_field_core_4 ( grid, id, setinitval_in , tl_in , inter_domain_in , okay_to_alloc_in, num_bytes_allocated , &
1381 sd31, ed31, sd32, ed32, sd33, ed33, &
1382 sm31 , em31 , sm32 , em32 , sm33 , em33 , &
1383 sp31 , ep31 , sp32 , ep32 , sp33 , ep33 , &
1384 sp31x, ep31x, sp32x, ep32x, sp33x, ep33x, &
1385 sp31y, ep31y, sp32y, ep32y, sp33y, ep33y, &
1386 sm31x, em31x, sm32x, em32x, sm33x, em33x, &
1387 sm31y, em31y, sm32y, em32y, sm33y, em33y )
1388 CALL alloc_space_field_core_5 ( grid, id, setinitval_in , tl_in , inter_domain_in , okay_to_alloc_in, num_bytes_allocated , &
1389 sd31, ed31, sd32, ed32, sd33, ed33, &
1390 sm31 , em31 , sm32 , em32 , sm33 , em33 , &
1391 sp31 , ep31 , sp32 , ep32 , sp33 , ep33 , &
1392 sp31x, ep31x, sp32x, ep32x, sp33x, ep33x, &
1393 sp31y, ep31y, sp32y, ep32y, sp33y, ep33y, &
1394 sm31x, em31x, sm32x, em32x, sm33x, em33x, &
1395 sm31y, em31y, sm32y, em32y, sm33y, em33y )
1396 CALL alloc_space_field_core_6 ( grid, id, setinitval_in , tl_in , inter_domain_in , okay_to_alloc_in, num_bytes_allocated , &
1397 sd31, ed31, sd32, ed32, sd33, ed33, &
1398 sm31 , em31 , sm32 , em32 , sm33 , em33 , &
1399 sp31 , ep31 , sp32 , ep32 , sp33 , ep33 , &
1400 sp31x, ep31x, sp32x, ep32x, sp33x, ep33x, &
1401 sp31y, ep31y, sp32y, ep32y, sp33y, ep33y, &
1402 sm31x, em31x, sm32x, em32x, sm33x, em33x, &
1403 sm31y, em31y, sm32y, em32y, sm33y, em33y )
1404 CALL alloc_space_field_core_7 ( grid, id, setinitval_in , tl_in , inter_domain_in , okay_to_alloc_in, num_bytes_allocated , &
1405 sd31, ed31, sd32, ed32, sd33, ed33, &
1406 sm31 , em31 , sm32 , em32 , sm33 , em33 , &
1407 sp31 , ep31 , sp32 , ep32 , sp33 , ep33 , &
1408 sp31x, ep31x, sp32x, ep32x, sp33x, ep33x, &
1409 sp31y, ep31y, sp32y, ep32y, sp33y, ep33y, &
1410 sm31x, em31x, sm32x, em32x, sm33x, em33x, &
1411 sm31y, em31y, sm32y, em32y, sm33y, em33y )
1412 CALL alloc_space_field_core_8 ( grid, id, setinitval_in , tl_in , inter_domain_in , okay_to_alloc_in, num_bytes_allocated , &
1413 sd31, ed31, sd32, ed32, sd33, ed33, &
1414 sm31 , em31 , sm32 , em32 , sm33 , em33 , &
1415 sp31 , ep31 , sp32 , ep32 , sp33 , ep33 , &
1416 sp31x, ep31x, sp32x, ep32x, sp33x, ep33x, &
1417 sp31y, ep31y, sp32y, ep32y, sp33y, ep33y, &
1418 sm31x, em31x, sm32x, em32x, sm33x, em33x, &
1419 sm31y, em31y, sm32y, em32y, sm33y, em33y )
1420 CALL alloc_space_field_core_9 ( grid, id, setinitval_in , tl_in , inter_domain_in , okay_to_alloc_in, num_bytes_allocated , &
1421 sd31, ed31, sd32, ed32, sd33, ed33, &
1422 sm31 , em31 , sm32 , em32 , sm33 , em33 , &
1423 sp31 , ep31 , sp32 , ep32 , sp33 , ep33 , &
1424 sp31x, ep31x, sp32x, ep32x, sp33x, ep33x, &
1425 sp31y, ep31y, sp32y, ep32y, sp33y, ep33y, &
1426 sm31x, em31x, sm32x, em32x, sm33x, em33x, &
1427 sm31y, em31y, sm32y, em32y, sm33y, em33y )
1429 IF ( .NOT. grid%have_displayed_alloc_stats ) THEN
1430 ! we do not want to see this message more than once, as can happen with the allocation and
1431 ! deallocation of intermediate domains used in nesting.
1432 WRITE(wrf_err_message,*)&
1433 'alloc_space_field: domain ',id,', ',num_bytes_allocated,' bytes allocated'
1434 CALL wrf_debug( 0, wrf_err_message )
1435 grid%have_displayed_alloc_stats = .TRUE.
1439 grid%alloced_sd31=sd31
1440 grid%alloced_ed31=ed31
1441 grid%alloced_sd32=sd32
1442 grid%alloced_ed32=ed32
1443 grid%alloced_sd33=sd33
1444 grid%alloced_ed33=ed33
1445 grid%alloced_sm31=sm31
1446 grid%alloced_em31=em31
1447 grid%alloced_sm32=sm32
1448 grid%alloced_em32=em32
1449 grid%alloced_sm33=sm33
1450 grid%alloced_em33=em33
1451 grid%alloced_sm31x=sm31x
1452 grid%alloced_em31x=em31x
1453 grid%alloced_sm32x=sm32x
1454 grid%alloced_em32x=em32x
1455 grid%alloced_sm33x=sm33x
1456 grid%alloced_em33x=em33x
1457 grid%alloced_sm31y=sm31y
1458 grid%alloced_em31y=em31y
1459 grid%alloced_sm32y=sm32y
1460 grid%alloced_em32y=em32y
1461 grid%alloced_sm33y=sm33y
1462 grid%alloced_em33y=em33y
1464 grid%allocated=.TRUE.
1466 END SUBROUTINE alloc_space_field
1468 ! Ensure_space_field allocates a grid's arrays if they are not yet
1469 ! allocated. If they were already allocated, then it deallocates and
1470 ! reallocates them if they were allocated with different dimensions.
1471 ! If they were already allocated with the requested dimensions, then
1472 ! ensure_space_field does nothing.
1474 SUBROUTINE ensure_space_field ( grid, id, setinitval_in , tl_in , inter_domain_in , okay_to_alloc_in, &
1475 sd31, ed31, sd32, ed32, sd33, ed33, &
1476 sm31 , em31 , sm32 , em32 , sm33 , em33 , &
1477 sp31 , ep31 , sp32 , ep32 , sp33 , ep33 , &
1478 sp31x, ep31x, sp32x, ep32x, sp33x, ep33x, &
1479 sp31y, ep31y, sp32y, ep32y, sp33y, ep33y, &
1480 sm31x, em31x, sm32x, em32x, sm33x, em33x, &
1481 sm31y, em31y, sm32y, em32y, sm33y, em33y )
1487 TYPE(domain) , POINTER :: grid
1488 INTEGER , INTENT(IN) :: id
1489 INTEGER , INTENT(IN) :: setinitval_in ! 3 = everything, 1 = arrays only, 0 = none
1490 INTEGER , INTENT(IN) :: sd31, ed31, sd32, ed32, sd33, ed33
1491 INTEGER , INTENT(IN) :: sm31, em31, sm32, em32, sm33, em33
1492 INTEGER , INTENT(IN) :: sp31, ep31, sp32, ep32, sp33, ep33
1493 INTEGER , INTENT(IN) :: sp31x, ep31x, sp32x, ep32x, sp33x, ep33x
1494 INTEGER , INTENT(IN) :: sp31y, ep31y, sp32y, ep32y, sp33y, ep33y
1495 INTEGER , INTENT(IN) :: sm31x, em31x, sm32x, em32x, sm33x, em33x
1496 INTEGER , INTENT(IN) :: sm31y, em31y, sm32y, em32y, sm33y, em33y
1498 ! this argument is a bitmask. First bit is time level 1, second is time level 2, and so on.
1499 ! e.g. to set both 1st and second time level, use 3
1500 ! to set only 1st use 1
1501 ! to set only 2st use 2
1502 INTEGER , INTENT(IN) :: tl_in
1504 ! true if the allocation is for an intermediate domain (for nesting); only certain fields allocated
1505 ! false otherwise (all allocated, modulo tl above)
1506 LOGICAL , INTENT(IN) :: inter_domain_in, okay_to_alloc_in
1507 LOGICAL :: size_changed
1509 size_changed= .not. ( &
1510 grid%alloced_sd31 .eq. sd31 .and. grid%alloced_ed31 .eq. ed31 .and. &
1511 grid%alloced_sd32 .eq. sd32 .and. grid%alloced_ed32 .eq. ed32 .and. &
1512 grid%alloced_sd33 .eq. sd33 .and. grid%alloced_ed33 .eq. ed33 .and. &
1513 grid%alloced_sm31 .eq. sm31 .and. grid%alloced_em31 .eq. em31 .and. &
1514 grid%alloced_sm32 .eq. sm32 .and. grid%alloced_em32 .eq. em32 .and. &
1515 grid%alloced_sm33 .eq. sm33 .and. grid%alloced_em33 .eq. em33 .and. &
1516 grid%alloced_sm31x .eq. sm31x .and. grid%alloced_em31x .eq. em31x .and. &
1517 grid%alloced_sm32x .eq. sm32x .and. grid%alloced_em32x .eq. em32x .and. &
1518 grid%alloced_sm33x .eq. sm33x .and. grid%alloced_em33x .eq. em33x .and. &
1519 grid%alloced_sm31y .eq. sm31y .and. grid%alloced_em31y .eq. em31y .and. &
1520 grid%alloced_sm32y .eq. sm32y .and. grid%alloced_em32y .eq. em32y .and. &
1521 grid%alloced_sm33y .eq. sm33y .and. grid%alloced_em33y .eq. em33y &
1523 if(.not. grid%allocated .or. size_changed) then
1524 if(.not. grid%allocated) then
1525 call wrf_debug(1,'ensure_space_field: calling alloc_space_field because a grid was not allocated.')
1528 call wrf_debug(1,'ensure_space_field: deallocating and reallocating a grid because grid size changed.')
1530 if(grid%allocated) &
1531 call dealloc_space_field( grid )
1532 call alloc_space_field ( grid, id, setinitval_in , tl_in , inter_domain_in , okay_to_alloc_in, &
1533 sd31, ed31, sd32, ed32, sd33, ed33, &
1534 sm31 , em31 , sm32 , em32 , sm33 , em33 , &
1535 sp31 , ep31 , sp32 , ep32 , sp33 , ep33 , &
1536 sp31x, ep31x, sp32x, ep32x, sp33x, ep33x, &
1537 sp31y, ep31y, sp32y, ep32y, sp33y, ep33y, &
1538 sm31x, em31x, sm32x, em32x, sm33x, em33x, &
1539 sm31y, em31y, sm32y, em32y, sm33y, em33y )
1542 END SUBROUTINE ensure_space_field
1544 ! This routine is used to DEALLOCATE space for a single domain and remove
1545 ! it from the linked list. First the pointers in the linked list are fixed
1546 ! (so the one in the middle can be removed). Then the domain itself is
1547 ! DEALLOCATEd via a call to domain_destroy().
1549 SUBROUTINE dealloc_space_domain ( id )
1555 INTEGER , INTENT(IN) :: id
1559 TYPE(domain) , POINTER :: grid
1562 ! Initializations required to start the routine.
1565 old_grid => head_grid
1568 ! The identity of the domain to delete is based upon the "id".
1569 ! We search all of the possible grids. It is required to find a domain
1570 ! otherwise it is a fatal error.
1572 find_grid : DO WHILE ( ASSOCIATED(grid) )
1573 IF ( grid%id == id ) THEN
1575 old_grid%next => grid%next
1576 CALL domain_destroy( grid )
1583 IF ( .NOT. found ) THEN
1584 WRITE ( wrf_err_message , * ) 'module_domain: ', &
1585 'dealloc_space_domain: Could not de-allocate grid id ',id
1586 CALL wrf_error_fatal ( TRIM( wrf_err_message ) )
1589 END SUBROUTINE dealloc_space_domain
1593 ! This routine is used to DEALLOCATE space for a single domain type.
1594 ! First, the field data are all removed through a CALL to the
1595 ! dealloc_space_field routine. Then the pointer to the domain
1596 ! itself is DEALLOCATEd.
1598 SUBROUTINE domain_destroy ( grid )
1604 TYPE(domain) , POINTER :: grid
1606 CALL dealloc_space_field ( grid )
1607 CALL dealloc_linked_lists( grid )
1608 DEALLOCATE( grid%parents )
1609 DEALLOCATE( grid%nests )
1610 ! clean up time manager bits
1611 CALL domain_clock_destroy( grid )
1612 CALL domain_alarms_destroy( grid )
1613 IF ( ASSOCIATED( grid%i_start ) ) THEN
1614 DEALLOCATE( grid%i_start )
1616 IF ( ASSOCIATED( grid%i_end ) ) THEN
1617 DEALLOCATE( grid%i_end )
1619 IF ( ASSOCIATED( grid%j_start ) ) THEN
1620 DEALLOCATE( grid%j_start )
1622 IF ( ASSOCIATED( grid%j_end ) ) THEN
1623 DEALLOCATE( grid%j_end )
1625 IF ( ASSOCIATED( grid%itsloc ) ) THEN
1626 DEALLOCATE( grid%itsloc )
1628 IF ( ASSOCIATED( grid%jtsloc ) ) THEN
1629 DEALLOCATE( grid%jtsloc )
1631 IF ( ASSOCIATED( grid%id_tsloc ) ) THEN
1632 DEALLOCATE( grid%id_tsloc )
1634 IF ( ASSOCIATED( grid%lattsloc ) ) THEN
1635 DEALLOCATE( grid%lattsloc )
1637 IF ( ASSOCIATED( grid%lontsloc ) ) THEN
1638 DEALLOCATE( grid%lontsloc )
1640 IF ( ASSOCIATED( grid%nametsloc ) ) THEN
1641 DEALLOCATE( grid%nametsloc )
1643 IF ( ASSOCIATED( grid%desctsloc ) ) THEN
1644 DEALLOCATE( grid%desctsloc )
1646 IF ( ASSOCIATED( grid%ts_filename ) ) THEN
1647 DEALLOCATE( grid%ts_filename )
1650 IF ( ASSOCIATED( grid%track_time_in ) ) THEN
1651 DEALLOCATE( grid%track_time_in )
1654 IF ( ASSOCIATED( grid%track_lat_in ) ) THEN
1655 DEALLOCATE( grid%track_lat_in )
1658 IF ( ASSOCIATED( grid%track_lon_in ) ) THEN
1659 DEALLOCATE( grid%track_lon_in )
1662 IF ( ASSOCIATED( grid%track_i ) ) THEN
1663 DEALLOCATE( grid%track_i )
1666 IF ( ASSOCIATED( grid%track_j ) ) THEN
1667 DEALLOCATE( grid%track_j )
1670 IF ( ASSOCIATED( grid%track_time_domain ) ) THEN
1671 DEALLOCATE( grid%track_time_domain )
1674 IF ( ASSOCIATED( grid%track_lat_domain ) ) THEN
1675 DEALLOCATE( grid%track_lat_domain )
1678 IF ( ASSOCIATED( grid%track_lon_domain ) ) THEN
1679 DEALLOCATE( grid%track_lon_domain )
1685 END SUBROUTINE domain_destroy
1687 SUBROUTINE dealloc_linked_lists ( grid )
1689 TYPE(domain), POINTER :: grid
1690 TYPE(fieldlist), POINTER :: p, q
1691 p => grid%head_statevars
1692 DO WHILE ( ASSOCIATED( p ) )
1693 if (p%varname.eq."chem_ic") exit
1694 q => p ; p => p%next ; DEALLOCATE(q)
1696 NULLIFY(grid%head_statevars) ; NULLIFY( grid%tail_statevars)
1698 IF ( .NOT. grid%is_intermediate ) THEN
1699 ALLOCATE( grid%head_statevars )
1700 NULLIFY( grid%head_statevars%next)
1701 grid%tail_statevars => grid%head_statevars
1704 END SUBROUTINE dealloc_linked_lists
1706 RECURSIVE SUBROUTINE show_nest_subtree ( grid )
1707 TYPE(domain), POINTER :: grid
1710 IF ( .NOT. ASSOCIATED( grid ) ) RETURN
1712 DO kid = 1, max_nests
1713 IF ( ASSOCIATED( grid%nests(kid)%ptr ) ) THEN
1714 IF ( grid%nests(kid)%ptr%id .EQ. myid ) THEN
1715 CALL wrf_error_fatal( 'show_nest_subtree: nest hierarchy corrupted' )
1717 CALL show_nest_subtree( grid%nests(kid)%ptr )
1720 END SUBROUTINE show_nest_subtree
1725 ! This routine DEALLOCATEs each gridded field for this domain. For each type of
1726 ! different array (1d, 2d, 3d, etc.), the space for each pointer is DEALLOCATEd
1727 ! for every -1 (i.e., each different meteorological field).
1729 SUBROUTINE dealloc_space_field ( grid )
1735 TYPE(domain) , POINTER :: grid
1741 # include "deallocs.inc"
1743 END SUBROUTINE dealloc_space_field
1747 RECURSIVE SUBROUTINE find_grid_by_id ( id, in_grid, result_grid )
1749 INTEGER, INTENT(IN) :: id
1750 TYPE(domain), POINTER :: in_grid
1751 TYPE(domain), POINTER :: result_grid
1753 ! This is a recursive subroutine that traverses the domain hierarchy rooted
1754 ! at the input argument <em>in_grid</em>, a pointer to TYPE(domain), and returns
1755 ! a pointer to the domain matching the integer argument <em>id</em> if it exists.
1758 TYPE(domain), POINTER :: grid_ptr
1762 NULLIFY(result_grid)
1763 IF ( ASSOCIATED( in_grid ) ) THEN
1764 IF ( in_grid%id .EQ. id ) THEN
1765 result_grid => in_grid
1768 DO WHILE ( ASSOCIATED( grid_ptr ) .AND. .NOT. found )
1769 DO kid = 1, max_nests
1770 IF ( ASSOCIATED( grid_ptr%nests(kid)%ptr ) .AND. .NOT. found ) THEN
1771 CALL find_grid_by_id ( id, grid_ptr%nests(kid)%ptr, result_grid )
1772 IF ( ASSOCIATED( result_grid ) ) THEN
1773 IF ( result_grid%id .EQ. id ) found = .TRUE.
1777 IF ( .NOT. found ) grid_ptr => grid_ptr%sibling
1782 END SUBROUTINE find_grid_by_id
1785 FUNCTION first_loc_integer ( array , search ) RESULT ( loc )
1791 INTEGER , INTENT(IN) , DIMENSION(:) :: array
1792 INTEGER , INTENT(IN) :: search
1799 ! This routine is used to find a specific domain identifier in an array
1800 ! of domain identifiers.
1809 find : DO loop = 1 , SIZE(array)
1810 IF ( search == array(loop) ) THEN
1816 END FUNCTION first_loc_integer
1818 SUBROUTINE init_module_domain
1819 END SUBROUTINE init_module_domain
1824 ! The following routines named domain_*() are convenience routines that
1825 ! eliminate many duplicated bits of code. They provide shortcuts for the
1826 ! most common operations on the domain_clock field of TYPE(domain).
1830 FUNCTION domain_get_current_time ( grid ) RESULT ( current_time )
1833 ! This convenience function returns the current time for domain grid.
1836 TYPE(domain), INTENT(IN) :: grid
1838 TYPE(WRFU_Time) :: current_time
1841 CALL WRFU_ClockGet( grid%domain_clock, CurrTime=current_time, &
1843 IF ( rc /= WRFU_SUCCESS ) THEN
1844 CALL wrf_error_fatal ( &
1845 'domain_get_current_time: WRFU_ClockGet failed' )
1847 END FUNCTION domain_get_current_time
1850 FUNCTION domain_get_start_time ( grid ) RESULT ( start_time )
1853 ! This convenience function returns the start time for domain grid.
1856 TYPE(domain), INTENT(IN) :: grid
1858 TYPE(WRFU_Time) :: start_time
1861 CALL WRFU_ClockGet( grid%domain_clock, StartTime=start_time, &
1863 IF ( rc /= WRFU_SUCCESS ) THEN
1864 CALL wrf_error_fatal ( &
1865 'domain_get_start_time: WRFU_ClockGet failed' )
1867 END FUNCTION domain_get_start_time
1870 FUNCTION domain_get_stop_time ( grid ) RESULT ( stop_time )
1873 ! This convenience function returns the stop time for domain grid.
1876 TYPE(domain), INTENT(IN) :: grid
1878 TYPE(WRFU_Time) :: stop_time
1881 CALL WRFU_ClockGet( grid%domain_clock, StopTime=stop_time, &
1883 IF ( rc /= WRFU_SUCCESS ) THEN
1884 CALL wrf_error_fatal ( &
1885 'domain_get_stop_time: WRFU_ClockGet failed' )
1887 END FUNCTION domain_get_stop_time
1890 FUNCTION domain_get_time_step ( grid ) RESULT ( time_step )
1893 ! This convenience function returns the time step for domain grid.
1896 TYPE(domain), INTENT(IN) :: grid
1898 TYPE(WRFU_TimeInterval) :: time_step
1901 CALL WRFU_ClockGet( grid%domain_clock, timeStep=time_step, &
1903 IF ( rc /= WRFU_SUCCESS ) THEN
1904 CALL wrf_error_fatal ( &
1905 'domain_get_time_step: WRFU_ClockGet failed' )
1907 END FUNCTION domain_get_time_step
1910 FUNCTION domain_get_advanceCount ( grid ) RESULT ( advanceCount )
1913 ! This convenience function returns the time step for domain grid.
1914 ! Also converts from INTEGER(WRFU_KIND_I8) to INTEGER.
1917 TYPE(domain), INTENT(IN) :: grid
1919 INTEGER :: advanceCount
1921 INTEGER(WRFU_KIND_I8) :: advanceCountLcl
1923 CALL WRFU_ClockGet( grid%domain_clock, &
1924 advanceCount=advanceCountLcl, &
1926 IF ( rc /= WRFU_SUCCESS ) THEN
1927 CALL wrf_error_fatal ( &
1928 'domain_get_advanceCount: WRFU_ClockGet failed' )
1930 advanceCount = advanceCountLcl
1931 END FUNCTION domain_get_advanceCount
1934 SUBROUTINE domain_alarms_destroy ( grid )
1937 ! This convenience routine destroys and deallocates all alarms associated
1941 TYPE(domain), INTENT(INOUT) :: grid
1945 IF ( ASSOCIATED( grid%alarms ) .AND. &
1946 ASSOCIATED( grid%alarms_created ) ) THEN
1947 DO alarmid = 1, MAX_WRF_ALARMS
1948 IF ( grid%alarms_created( alarmid ) ) THEN
1949 CALL WRFU_AlarmDestroy( grid%alarms( alarmid ) )
1950 grid%alarms_created( alarmid ) = .FALSE.
1953 DEALLOCATE( grid%alarms )
1954 NULLIFY( grid%alarms )
1955 DEALLOCATE( grid%alarms_created )
1956 NULLIFY( grid%alarms_created )
1958 END SUBROUTINE domain_alarms_destroy
1961 SUBROUTINE domain_clock_destroy ( grid )
1964 ! This convenience routine destroys and deallocates the domain clock.
1967 TYPE(domain), INTENT(INOUT) :: grid
1968 IF ( ASSOCIATED( grid%domain_clock ) ) THEN
1969 IF ( grid%domain_clock_created ) THEN
1970 CALL WRFU_ClockDestroy( grid%domain_clock )
1971 grid%domain_clock_created = .FALSE.
1973 DEALLOCATE( grid%domain_clock )
1974 NULLIFY( grid%domain_clock )
1976 END SUBROUTINE domain_clock_destroy
1979 FUNCTION domain_last_time_step ( grid ) RESULT ( LAST_TIME )
1982 ! This convenience function returns .TRUE. if this is the last time
1983 ! step for domain grid. Thanks to Tom Black.
1986 TYPE(domain), INTENT(IN) :: grid
1988 LOGICAL :: LAST_TIME
1989 LAST_TIME = domain_get_stop_time( grid ) .EQ. &
1990 ( domain_get_current_time( grid ) + &
1991 domain_get_time_step( grid ) )
1992 END FUNCTION domain_last_time_step
1996 FUNCTION domain_clockisstoptime ( grid ) RESULT ( is_stop_time )
1999 ! This convenience function returns .TRUE. iff grid%clock has reached its
2003 TYPE(domain), INTENT(IN) :: grid
2005 LOGICAL :: is_stop_time
2007 is_stop_time = WRFU_ClockIsStopTime( grid%domain_clock , rc=rc )
2008 IF ( rc /= WRFU_SUCCESS ) THEN
2009 CALL wrf_error_fatal ( &
2010 'domain_clockisstoptime: WRFU_ClockIsStopTime() failed' )
2012 END FUNCTION domain_clockisstoptime
2016 FUNCTION domain_clockisstopsubtime ( grid ) RESULT ( is_stop_subtime )
2019 ! This convenience function returns .TRUE. iff grid%clock has reached its
2020 ! grid%stop_subtime.
2023 TYPE(domain), INTENT(IN) :: grid
2025 LOGICAL :: is_stop_subtime
2027 TYPE(WRFU_TimeInterval) :: timeStep
2028 TYPE(WRFU_Time) :: currentTime
2029 LOGICAL :: positive_timestep
2030 is_stop_subtime = .FALSE.
2031 CALL domain_clock_get( grid, time_step=timeStep, &
2032 current_time=currentTime )
2033 positive_timestep = ESMF_TimeIntervalIsPositive( timeStep )
2034 IF ( positive_timestep ) THEN
2035 ! hack for bug in PGI 5.1-x
2036 ! IF ( currentTime .GE. grid%stop_subtime ) THEN
2037 IF ( ESMF_TimeGE( currentTime, grid%stop_subtime ) ) THEN
2038 is_stop_subtime = .TRUE.
2041 ! hack for bug in PGI 5.1-x
2042 ! IF ( currentTime .LE. grid%stop_subtime ) THEN
2043 IF ( ESMF_TimeLE( currentTime, grid%stop_subtime ) ) THEN
2044 is_stop_subtime = .TRUE.
2047 END FUNCTION domain_clockisstopsubtime
2052 FUNCTION domain_get_sim_start_time ( grid ) RESULT ( simulationStartTime )
2055 ! This convenience routine returns simulation start time for domain grid as
2058 ! If this is not a restart run, the start_time of head_grid%clock is returned
2061 ! Note that simulation start time remains constant through restarts while
2062 ! the start_time of head_grid%clock always refers to the start time of the
2063 ! current run (restart or otherwise).
2066 TYPE(domain), INTENT(IN) :: grid
2068 TYPE(WRFU_Time) :: simulationStartTime
2071 INTEGER :: simulation_start_year, simulation_start_month, &
2072 simulation_start_day, simulation_start_hour , &
2073 simulation_start_minute, simulation_start_second
2074 CALL nl_get_simulation_start_year ( 1, simulation_start_year )
2075 CALL nl_get_simulation_start_month ( 1, simulation_start_month )
2076 CALL nl_get_simulation_start_day ( 1, simulation_start_day )
2077 CALL nl_get_simulation_start_hour ( 1, simulation_start_hour )
2078 CALL nl_get_simulation_start_minute ( 1, simulation_start_minute )
2079 CALL nl_get_simulation_start_second ( 1, simulation_start_second )
2080 CALL WRFU_TimeSet( simulationStartTime, &
2081 YY=simulation_start_year, &
2082 MM=simulation_start_month, &
2083 DD=simulation_start_day, &
2084 H=simulation_start_hour, &
2085 M=simulation_start_minute, &
2086 S=simulation_start_second, &
2088 IF ( rc /= WRFU_SUCCESS ) THEN
2089 CALL nl_get_start_year ( 1, simulation_start_year )
2090 CALL nl_get_start_month ( 1, simulation_start_month )
2091 CALL nl_get_start_day ( 1, simulation_start_day )
2092 CALL nl_get_start_hour ( 1, simulation_start_hour )
2093 CALL nl_get_start_minute ( 1, simulation_start_minute )
2094 CALL nl_get_start_second ( 1, simulation_start_second )
2095 CALL wrf_debug( 150, "WARNING: domain_get_sim_start_time using head_grid start time from namelist" )
2096 CALL WRFU_TimeSet( simulationStartTime, &
2097 YY=simulation_start_year, &
2098 MM=simulation_start_month, &
2099 DD=simulation_start_day, &
2100 H=simulation_start_hour, &
2101 M=simulation_start_minute, &
2102 S=simulation_start_second, &
2106 END FUNCTION domain_get_sim_start_time
2108 FUNCTION domain_get_time_since_sim_start ( grid ) RESULT ( time_since_sim_start )
2111 ! This convenience function returns the time elapsed since start of
2112 ! simulation for domain grid.
2114 ! Note that simulation start time remains constant through restarts while
2115 ! the start_time of grid%clock always refers to the start time of the
2116 ! current run (restart or otherwise).
2119 TYPE(domain), INTENT(IN) :: grid
2121 TYPE(WRFU_TimeInterval) :: time_since_sim_start
2123 TYPE(WRFU_Time) :: lcl_currtime, lcl_simstarttime
2124 lcl_simstarttime = domain_get_sim_start_time( grid )
2125 lcl_currtime = domain_get_current_time ( grid )
2126 time_since_sim_start = lcl_currtime - lcl_simstarttime
2127 END FUNCTION domain_get_time_since_sim_start
2132 SUBROUTINE domain_clock_get( grid, current_time, &
2134 current_timestr_frac, &
2135 start_time, start_timestr, &
2136 stop_time, stop_timestr, &
2137 time_step, time_stepstr, &
2138 time_stepstr_frac, &
2140 currentDayOfYearReal, &
2141 minutesSinceSimulationStart, &
2142 timeSinceSimulationStart, &
2143 simulationStartTime, &
2144 simulationStartTimeStr )
2146 TYPE(domain), INTENT(IN) :: grid
2147 TYPE(WRFU_Time), INTENT( OUT), OPTIONAL :: current_time
2148 CHARACTER (LEN=*), INTENT( OUT), OPTIONAL :: current_timestr
2149 CHARACTER (LEN=*), INTENT( OUT), OPTIONAL :: current_timestr_frac
2150 TYPE(WRFU_Time), INTENT( OUT), OPTIONAL :: start_time
2151 CHARACTER (LEN=*), INTENT( OUT), OPTIONAL :: start_timestr
2152 TYPE(WRFU_Time), INTENT( OUT), OPTIONAL :: stop_time
2153 CHARACTER (LEN=*), INTENT( OUT), OPTIONAL :: stop_timestr
2154 TYPE(WRFU_TimeInterval), INTENT( OUT), OPTIONAL :: time_step
2155 CHARACTER (LEN=*), INTENT( OUT), OPTIONAL :: time_stepstr
2156 CHARACTER (LEN=*), INTENT( OUT), OPTIONAL :: time_stepstr_frac
2157 INTEGER, INTENT( OUT), OPTIONAL :: advanceCount
2158 ! currentDayOfYearReal = 0.0 at 0Z on 1 January, 0.5 at 12Z on
2160 REAL, INTENT( OUT), OPTIONAL :: currentDayOfYearReal
2161 ! Time at which simulation started. If this is not a restart run,
2162 ! start_time is returned instead.
2163 TYPE(WRFU_Time), INTENT( OUT), OPTIONAL :: simulationStartTime
2164 CHARACTER (LEN=*), INTENT( OUT), OPTIONAL :: simulationStartTimeStr
2165 ! time interval since start of simulation, includes effects of
2166 ! restarting even when restart uses a different timestep
2167 TYPE(WRFU_TimeInterval), INTENT( OUT), OPTIONAL :: timeSinceSimulationStart
2168 ! minutes since simulation start date
2169 REAL, INTENT( OUT), OPTIONAL :: minutesSinceSimulationStart
2171 ! This convenience routine returns clock information for domain grid in
2172 ! various forms. The caller is responsible for ensuring that character
2173 ! string actual arguments are big enough.
2177 TYPE(WRFU_Time) :: lcl_currtime, lcl_stoptime, lcl_starttime
2178 TYPE(WRFU_Time) :: lcl_simulationStartTime
2179 TYPE(WRFU_TimeInterval) :: lcl_time_step, lcl_timeSinceSimulationStart
2180 INTEGER :: days, seconds, Sn, Sd, rc
2181 CHARACTER (LEN=256) :: tmp_str
2182 CHARACTER (LEN=256) :: frac_str
2183 REAL(WRFU_KIND_R8) :: currentDayOfYearR8
2184 IF ( PRESENT( start_time ) ) THEN
2185 start_time = domain_get_start_time ( grid )
2187 IF ( PRESENT( start_timestr ) ) THEN
2188 lcl_starttime = domain_get_start_time ( grid )
2189 CALL wrf_timetoa ( lcl_starttime, start_timestr )
2191 IF ( PRESENT( time_step ) ) THEN
2192 time_step = domain_get_time_step ( grid )
2194 IF ( PRESENT( time_stepstr ) ) THEN
2195 lcl_time_step = domain_get_time_step ( grid )
2196 CALL WRFU_TimeIntervalGet( lcl_time_step, &
2197 timeString=time_stepstr, rc=rc )
2198 IF ( rc /= WRFU_SUCCESS ) THEN
2199 CALL wrf_error_fatal ( &
2200 'domain_clock_get: WRFU_TimeIntervalGet() failed' )
2203 IF ( PRESENT( time_stepstr_frac ) ) THEN
2204 lcl_time_step = domain_get_time_step ( grid )
2205 CALL WRFU_TimeIntervalGet( lcl_time_step, timeString=tmp_str, &
2206 Sn=Sn, Sd=Sd, rc=rc )
2207 IF ( rc /= WRFU_SUCCESS ) THEN
2208 CALL wrf_error_fatal ( &
2209 'domain_clock_get: WRFU_TimeIntervalGet() failed' )
2211 CALL fraction_to_string( Sn, Sd, frac_str )
2212 time_stepstr_frac = TRIM(tmp_str)//TRIM(frac_str)
2214 IF ( PRESENT( advanceCount ) ) THEN
2215 advanceCount = domain_get_advanceCount ( grid )
2217 ! This duplication avoids assignment of time-manager objects
2218 ! which works now in ESMF 2.2.0 but may not work in the future
2219 ! if these objects become "deep". We have already been bitten
2220 ! by this when the clock objects were changed from "shallow" to
2221 ! "deep". Once again, adherence to orthodox canonical form by
2222 ! ESMF would avoid all this crap.
2223 IF ( PRESENT( current_time ) ) THEN
2224 current_time = domain_get_current_time ( grid )
2226 IF ( PRESENT( current_timestr ) ) THEN
2227 lcl_currtime = domain_get_current_time ( grid )
2228 CALL wrf_timetoa ( lcl_currtime, current_timestr )
2230 ! current time string including fractional part, if present
2231 IF ( PRESENT( current_timestr_frac ) ) THEN
2232 lcl_currtime = domain_get_current_time ( grid )
2233 CALL wrf_timetoa ( lcl_currtime, tmp_str )
2234 CALL WRFU_TimeGet( lcl_currtime, Sn=Sn, Sd=Sd, rc=rc )
2235 IF ( rc /= WRFU_SUCCESS ) THEN
2236 CALL wrf_error_fatal ( &
2237 'domain_clock_get: WRFU_TimeGet() failed' )
2239 CALL fraction_to_string( Sn, Sd, frac_str )
2240 current_timestr_frac = TRIM(tmp_str)//TRIM(frac_str)
2242 IF ( PRESENT( stop_time ) ) THEN
2243 stop_time = domain_get_stop_time ( grid )
2245 IF ( PRESENT( stop_timestr ) ) THEN
2246 lcl_stoptime = domain_get_stop_time ( grid )
2247 CALL wrf_timetoa ( lcl_stoptime, stop_timestr )
2249 IF ( PRESENT( currentDayOfYearReal ) ) THEN
2250 lcl_currtime = domain_get_current_time ( grid )
2251 CALL WRFU_TimeGet( lcl_currtime, dayOfYear_r8=currentDayOfYearR8, &
2253 IF ( rc /= WRFU_SUCCESS ) THEN
2254 CALL wrf_error_fatal ( &
2255 'domain_clock_get: WRFU_TimeGet(dayOfYear_r8) failed' )
2257 currentDayOfYearReal = REAL( currentDayOfYearR8 ) - 1.0
2259 IF ( PRESENT( simulationStartTime ) ) THEN
2260 simulationStartTime = domain_get_sim_start_time( grid )
2262 IF ( PRESENT( simulationStartTimeStr ) ) THEN
2263 lcl_simulationStartTime = domain_get_sim_start_time( grid )
2264 CALL wrf_timetoa ( lcl_simulationStartTime, simulationStartTimeStr )
2266 IF ( PRESENT( timeSinceSimulationStart ) ) THEN
2267 timeSinceSimulationStart = domain_get_time_since_sim_start( grid )
2269 IF ( PRESENT( minutesSinceSimulationStart ) ) THEN
2270 lcl_timeSinceSimulationStart = domain_get_time_since_sim_start( grid )
2271 CALL WRFU_TimeIntervalGet( lcl_timeSinceSimulationStart, &
2272 D=days, S=seconds, Sn=Sn, Sd=Sd, rc=rc )
2273 IF ( rc /= WRFU_SUCCESS ) THEN
2274 CALL wrf_error_fatal ( &
2275 'domain_clock_get: WRFU_TimeIntervalGet() failed' )
2277 ! get rid of hard-coded constants
2278 minutesSinceSimulationStart = ( REAL( days ) * 24. * 60. ) + &
2279 ( REAL( seconds ) / 60. )
2281 minutesSinceSimulationStart = minutesSinceSimulationStart + &
2282 ( ( REAL( Sn ) / REAL( Sd ) ) / 60. )
2286 END SUBROUTINE domain_clock_get
2288 FUNCTION domain_clockisstarttime ( grid ) RESULT ( is_start_time )
2291 ! This convenience function returns .TRUE. iff grid%clock is at its
2295 TYPE(domain), INTENT(IN) :: grid
2297 LOGICAL :: is_start_time
2298 TYPE(WRFU_Time) :: start_time, current_time
2299 CALL domain_clock_get( grid, current_time=current_time, &
2300 start_time=start_time )
2301 is_start_time = ( current_time == start_time )
2302 END FUNCTION domain_clockisstarttime
2304 FUNCTION domain_clockissimstarttime ( grid ) RESULT ( is_sim_start_time )
2307 ! This convenience function returns .TRUE. iff grid%clock is at the
2308 ! simulation start time. (It returns .FALSE. during a restart run.)
2311 TYPE(domain), INTENT(IN) :: grid
2313 LOGICAL :: is_sim_start_time
2314 TYPE(WRFU_Time) :: simulationStartTime, current_time
2315 CALL domain_clock_get( grid, current_time=current_time, &
2316 simulationStartTime=simulationStartTime )
2317 is_sim_start_time = ( current_time == simulationStartTime )
2318 END FUNCTION domain_clockissimstarttime
2323 SUBROUTINE domain_clock_create( grid, StartTime, &
2327 TYPE(domain), INTENT(INOUT) :: grid
2328 TYPE(WRFU_Time), INTENT(IN ) :: StartTime
2329 TYPE(WRFU_Time), INTENT(IN ) :: StopTime
2330 TYPE(WRFU_TimeInterval), INTENT(IN ) :: TimeStep
2332 ! This convenience routine creates the domain_clock for domain grid and
2333 ! sets associated flags.
2338 grid%domain_clock = WRFU_ClockCreate( TimeStep= TimeStep, &
2339 StartTime=StartTime, &
2340 StopTime= StopTime, &
2342 IF ( rc /= WRFU_SUCCESS ) THEN
2343 CALL wrf_error_fatal ( &
2344 'domain_clock_create: WRFU_ClockCreate() failed' )
2346 grid%domain_clock_created = .TRUE.
2348 END SUBROUTINE domain_clock_create
2352 SUBROUTINE domain_alarm_create( grid, alarm_id, interval, &
2353 begin_time, end_time )
2356 TYPE(domain), POINTER :: grid
2357 INTEGER, INTENT(IN) :: alarm_id
2358 TYPE(WRFU_TimeInterval), INTENT(IN), OPTIONAL :: interval
2359 TYPE(WRFU_TimeInterval), INTENT(IN), OPTIONAL :: begin_time
2360 TYPE(WRFU_TimeInterval), INTENT(IN), OPTIONAL :: end_time
2362 ! This convenience routine creates alarm alarm_id for domain grid and
2363 ! sets associated flags.
2368 !$$$ TBH: Ideally, this could be simplified by passing all optional actual
2369 !$$$ TBH: args into AlarmCreate. However, since operations are performed on
2370 !$$$ TBH: the actual args in-place in the calls, they must be present for the
2371 !$$$ TBH: operations themselves to be defined. Grrr...
2372 LOGICAL :: interval_only, all_args, no_args
2373 TYPE(WRFU_Time) :: startTime
2374 interval_only = .FALSE.
2377 IF ( ( .NOT. PRESENT( begin_time ) ) .AND. &
2378 ( .NOT. PRESENT( end_time ) ) .AND. &
2379 ( PRESENT( interval ) ) ) THEN
2380 interval_only = .TRUE.
2381 ELSE IF ( ( .NOT. PRESENT( begin_time ) ) .AND. &
2382 ( .NOT. PRESENT( end_time ) ) .AND. &
2383 ( .NOT. PRESENT( interval ) ) ) THEN
2385 ELSE IF ( ( PRESENT( begin_time ) ) .AND. &
2386 ( PRESENT( end_time ) ) .AND. &
2387 ( PRESENT( interval ) ) ) THEN
2390 CALL wrf_error_fatal ( &
2391 'ERROR in domain_alarm_create: bad argument list' )
2393 CALL domain_clock_get( grid, start_time=startTime )
2394 IF ( interval_only ) THEN
2395 grid%io_intervals( alarm_id ) = interval
2396 grid%alarms( alarm_id ) = &
2397 WRFU_AlarmCreate( clock=grid%domain_clock, &
2398 RingInterval=interval, &
2400 ELSE IF ( no_args ) THEN
2401 grid%alarms( alarm_id ) = &
2402 WRFU_AlarmCreate( clock=grid%domain_clock, &
2403 RingTime=startTime, &
2405 ELSE IF ( all_args ) THEN
2406 grid%io_intervals( alarm_id ) = interval
2407 grid%alarms( alarm_id ) = &
2408 WRFU_AlarmCreate( clock=grid%domain_clock, &
2409 RingTime=startTime + begin_time, &
2410 RingInterval=interval, &
2411 StopTime=startTime + end_time, &
2414 IF ( rc /= WRFU_SUCCESS ) THEN
2415 CALL wrf_error_fatal ( &
2416 'domain_alarm_create: WRFU_AlarmCreate() failed' )
2418 CALL WRFU_AlarmRingerOff( grid%alarms( alarm_id ) , rc=rc )
2419 IF ( rc /= WRFU_SUCCESS ) THEN
2420 CALL wrf_error_fatal ( &
2421 'domain_alarm_create: WRFU_AlarmRingerOff() failed' )
2423 grid%alarms_created( alarm_id ) = .TRUE.
2424 END SUBROUTINE domain_alarm_create
2428 SUBROUTINE domain_clock_set( grid, current_timestr, &
2432 TYPE(domain), INTENT(INOUT) :: grid
2433 CHARACTER (LEN=*), INTENT(IN ), OPTIONAL :: current_timestr
2434 CHARACTER (LEN=*), INTENT(IN ), OPTIONAL :: stop_timestr
2435 INTEGER, INTENT(IN ), OPTIONAL :: time_step_seconds
2437 ! This convenience routine sets clock information for domain grid.
2438 ! The caller is responsible for ensuring that character string actual
2439 ! arguments are big enough.
2443 TYPE(WRFU_Time) :: lcl_currtime, lcl_stoptime
2444 TYPE(WRFU_TimeInterval) :: tmpTimeInterval
2446 IF ( PRESENT( current_timestr ) ) THEN
2447 CALL wrf_atotime( current_timestr(1:19), lcl_currtime )
2448 CALL WRFU_ClockSet( grid%domain_clock, currTime=lcl_currtime, &
2450 IF ( rc /= WRFU_SUCCESS ) THEN
2451 CALL wrf_error_fatal ( &
2452 'domain_clock_set: WRFU_ClockSet(CurrTime) failed' )
2455 IF ( PRESENT( stop_timestr ) ) THEN
2456 CALL wrf_atotime( stop_timestr(1:19), lcl_stoptime )
2457 CALL WRFU_ClockSet( grid%domain_clock, stopTime=lcl_stoptime, &
2459 IF ( rc /= WRFU_SUCCESS ) THEN
2460 CALL wrf_error_fatal ( &
2461 'domain_clock_set: WRFU_ClockSet(StopTime) failed' )
2464 IF ( PRESENT( time_step_seconds ) ) THEN
2465 CALL WRFU_TimeIntervalSet( tmpTimeInterval, &
2466 S=time_step_seconds, rc=rc )
2467 IF ( rc /= WRFU_SUCCESS ) THEN
2468 CALL wrf_error_fatal ( &
2469 'domain_clock_set: WRFU_TimeIntervalSet failed' )
2471 CALL WRFU_ClockSet ( grid%domain_clock, &
2472 timeStep=tmpTimeInterval, &
2474 IF ( rc /= WRFU_SUCCESS ) THEN
2475 CALL wrf_error_fatal ( &
2476 'domain_clock_set: WRFU_ClockSet(TimeStep) failed' )
2480 END SUBROUTINE domain_clock_set
2483 ! Debug routine to print key clock information.
2484 ! Printed lines include pre_str.
2485 SUBROUTINE domain_clockprint ( level, grid, pre_str )
2487 INTEGER, INTENT( IN) :: level
2488 TYPE(domain), INTENT( IN) :: grid
2489 CHARACTER (LEN=*), INTENT( IN) :: pre_str
2490 CALL wrf_clockprint ( level, grid%domain_clock, pre_str )
2492 END SUBROUTINE domain_clockprint
2495 ! Advance the clock associated with grid.
2496 ! Also updates several derived time quantities in grid state.
2497 SUBROUTINE domain_clockadvance ( grid )
2499 TYPE(domain), INTENT(INOUT) :: grid
2501 CALL domain_clockprint ( 250, grid, &
2502 'DEBUG domain_clockadvance(): before WRFU_ClockAdvance,' )
2503 CALL WRFU_ClockAdvance( grid%domain_clock, rc=rc )
2504 IF ( rc /= WRFU_SUCCESS ) THEN
2505 CALL wrf_error_fatal ( &
2506 'domain_clockadvance: WRFU_ClockAdvance() failed' )
2508 CALL domain_clockprint ( 250, grid, &
2509 'DEBUG domain_clockadvance(): after WRFU_ClockAdvance,' )
2510 ! Update derived time quantities in grid state.
2511 ! These are initialized in setup_timekeeping().
2512 CALL domain_clock_get( grid, minutesSinceSimulationStart=grid%xtime )
2513 CALL domain_clock_get( grid, currentDayOfYearReal=grid%julian )
2515 END SUBROUTINE domain_clockadvance
2519 ! Set grid%gmt, grid%julday, and grid%julyr from simulation-start-date.
2520 ! Set start_of_simulation to TRUE iff current_time == simulation_start_time
2521 SUBROUTINE domain_setgmtetc ( grid, start_of_simulation )
2523 TYPE (domain), INTENT(INOUT) :: grid
2524 LOGICAL, INTENT( OUT) :: start_of_simulation
2526 CHARACTER (LEN=132) :: message
2527 TYPE(WRFU_Time) :: simStartTime
2528 INTEGER :: hr, mn, sec, ms, rc
2529 CALL domain_clockprint(150, grid, &
2530 'DEBUG domain_setgmtetc(): get simStartTime from clock,')
2531 CALL domain_clock_get( grid, simulationStartTime=simStartTime, &
2532 simulationStartTimeStr=message )
2533 CALL WRFU_TimeGet( simStartTime, YY=grid%julyr, dayOfYear=grid%julday, &
2534 H=hr, M=mn, S=sec, MS=ms, rc=rc)
2535 IF ( rc /= WRFU_SUCCESS ) THEN
2536 CALL wrf_error_fatal ( &
2537 'domain_setgmtetc: WRFU_TimeGet() failed' )
2539 WRITE( wrf_err_message , * ) 'DEBUG domain_setgmtetc(): simulation start time = [',TRIM( message ),']'
2540 CALL wrf_debug( 150, TRIM(wrf_err_message) )
2541 grid%gmt=hr+real(mn)/60.+real(sec)/3600.+real(ms)/(1000*3600)
2542 WRITE( wrf_err_message , * ) 'DEBUG domain_setgmtetc(): julyr,hr,mn,sec,ms,julday = ', &
2543 grid%julyr,hr,mn,sec,ms,grid%julday
2544 CALL wrf_debug( 150, TRIM(wrf_err_message) )
2545 WRITE( wrf_err_message , * ) 'DEBUG domain_setgmtetc(): gmt = ',grid%gmt
2546 CALL wrf_debug( 150, TRIM(wrf_err_message) )
2547 start_of_simulation = domain_ClockIsSimStartTime(grid)
2549 END SUBROUTINE domain_setgmtetc
2553 ! Set pointer to current grid.
2554 ! To begin with, current grid is not set.
2555 SUBROUTINE set_current_grid_ptr( grid_ptr )
2557 TYPE(domain), POINTER :: grid_ptr
2558 !PRINT *,'DEBUG: begin set_current_grid_ptr()'
2559 !IF ( ASSOCIATED( grid_ptr ) ) THEN
2560 ! PRINT *,'DEBUG: set_current_grid_ptr(): current_grid is associated'
2562 ! PRINT *,'DEBUG: set_current_grid_ptr(): current_grid is NOT associated'
2564 current_grid_set = .TRUE.
2565 current_grid => grid_ptr
2566 !PRINT *,'DEBUG: end set_current_grid_ptr()'
2567 END SUBROUTINE set_current_grid_ptr
2571 !******************************************************************************
2572 ! From Uli Blahak (01 Dec 2006)
2573 ! UB: Function to determine if the next time step is an alarm-timestep for a certain grid:
2574 !******************************************************************************
2576 LOGICAL FUNCTION Is_alarm_tstep( grid_clock, alarm )
2580 TYPE (WRFU_Clock), INTENT(in) :: grid_clock
2581 TYPE (WRFU_Alarm), INTENT(in) :: alarm
2583 LOGICAL :: pred1, pred2, pred3
2585 Is_alarm_tstep = .FALSE.
2587 IF ( ASSOCIATED( alarm%alarmint ) ) THEN
2588 IF ( alarm%alarmint%Enabled ) THEN
2589 IF ( alarm%alarmint%RingIntervalSet ) THEN
2590 pred1 = .FALSE. ; pred2 = .FALSE. ; pred3 = .FALSE.
2591 IF ( alarm%alarmint%StopTimeSet ) THEN
2592 PRED1 = ( grid_clock%clockint%CurrTime + grid_clock%clockint%TimeStep > &
2593 alarm%alarmint%StopTime )
2595 IF ( alarm%alarmint%RingTimeSet ) THEN
2596 PRED2 = ( ( alarm%alarmint%RingTime - &
2597 grid_clock%clockint%TimeStep <= &
2598 grid_clock%clockint%CurrTime ) &
2599 .AND. ( grid_clock%clockint%CurrTime < alarm%alarmint%RingTime ) )
2601 IF ( alarm%alarmint%RingIntervalSet ) THEN
2602 PRED3 = ( alarm%alarmint%PrevRingTime + &
2603 alarm%alarmint%RingInterval <= &
2604 grid_clock%clockint%CurrTime + grid_clock%clockint%TimeStep )
2606 IF ( ( .NOT. ( pred1 ) ) .AND. &
2607 ( ( pred2 ) .OR. ( pred3 ) ) ) THEN
2608 Is_alarm_tstep = .TRUE.
2610 ELSE IF ( alarm%alarmint%RingTimeSet ) THEN
2611 IF ( alarm%alarmint%RingTime -&
2612 grid_clock%clockint%TimeStep <= &
2613 grid_clock%clockint%CurrTime ) THEN
2614 Is_alarm_tstep = .TRUE.
2620 END FUNCTION Is_alarm_tstep
2623 !******************************************************************************
2624 ! BEGIN TEST SECTION
2625 ! Code in the test section is used to test domain methods.
2626 ! This code should probably be moved elsewhere, eventually.
2627 !******************************************************************************
2629 ! Private utility routines for domain_time_test.
2630 SUBROUTINE domain_time_test_print ( pre_str, name_str, res_str )
2632 CHARACTER (LEN=*), INTENT(IN) :: pre_str
2633 CHARACTER (LEN=*), INTENT(IN) :: name_str
2634 CHARACTER (LEN=*), INTENT(IN) :: res_str
2635 CHARACTER (LEN=512) :: out_str
2637 FMT="('DOMAIN_TIME_TEST ',A,': ',A,' = ',A)") &
2638 TRIM(pre_str), TRIM(name_str), TRIM(res_str)
2639 CALL wrf_debug( 0, TRIM(out_str) )
2640 END SUBROUTINE domain_time_test_print
2642 ! Test adjust_io_timestr
2643 SUBROUTINE test_adjust_io_timestr( TI_h, TI_m, TI_s, &
2644 CT_yy, CT_mm, CT_dd, CT_h, CT_m, CT_s, &
2645 ST_yy, ST_mm, ST_dd, ST_h, ST_m, ST_s, &
2647 INTEGER, INTENT(IN) :: TI_H
2648 INTEGER, INTENT(IN) :: TI_M
2649 INTEGER, INTENT(IN) :: TI_S
2650 INTEGER, INTENT(IN) :: CT_YY
2651 INTEGER, INTENT(IN) :: CT_MM ! month
2652 INTEGER, INTENT(IN) :: CT_DD ! day of month
2653 INTEGER, INTENT(IN) :: CT_H
2654 INTEGER, INTENT(IN) :: CT_M
2655 INTEGER, INTENT(IN) :: CT_S
2656 INTEGER, INTENT(IN) :: ST_YY
2657 INTEGER, INTENT(IN) :: ST_MM ! month
2658 INTEGER, INTENT(IN) :: ST_DD ! day of month
2659 INTEGER, INTENT(IN) :: ST_H
2660 INTEGER, INTENT(IN) :: ST_M
2661 INTEGER, INTENT(IN) :: ST_S
2662 CHARACTER (LEN=*), INTENT(IN) :: res_str
2663 CHARACTER (LEN=*), INTENT(IN) :: testname
2665 TYPE(WRFU_TimeInterval) :: TI
2666 TYPE(WRFU_Time) :: CT, ST
2667 LOGICAL :: test_passed
2669 CHARACTER(LEN=WRFU_MAXSTR) :: TI_str, CT_str, ST_str, computed_str
2671 CALL WRFU_TimeIntervalSet( TI, H=TI_H, M=TI_M, S=TI_S, rc=rc )
2672 CALL wrf_check_error( WRFU_SUCCESS, rc, &
2673 'FAIL: '//TRIM(testname)//'WRFU_TimeIntervalSet() ', &
2676 CALL WRFU_TimeIntervalGet( TI, timeString=TI_str, rc=rc )
2677 CALL wrf_check_error( WRFU_SUCCESS, rc, &
2678 'FAIL: '//TRIM(testname)//'WRFU_TimeGet() ', &
2682 CALL WRFU_TimeSet( CT, YY=CT_YY, MM=CT_MM, DD=CT_DD , &
2683 H=CT_H, M=CT_M, S=CT_S, rc=rc )
2684 CALL wrf_check_error( WRFU_SUCCESS, rc, &
2685 'FAIL: '//TRIM(testname)//'WRFU_TimeSet() ', &
2688 CALL WRFU_TimeGet( CT, timeString=CT_str, rc=rc )
2689 CALL wrf_check_error( WRFU_SUCCESS, rc, &
2690 'FAIL: '//TRIM(testname)//'WRFU_TimeGet() ', &
2694 CALL WRFU_TimeSet( ST, YY=ST_YY, MM=ST_MM, DD=ST_DD , &
2695 H=ST_H, M=ST_M, S=ST_S, rc=rc )
2696 CALL wrf_check_error( WRFU_SUCCESS, rc, &
2697 'FAIL: '//TRIM(testname)//'WRFU_TimeSet() ', &
2700 CALL WRFU_TimeGet( ST, timeString=ST_str, rc=rc )
2701 CALL wrf_check_error( WRFU_SUCCESS, rc, &
2702 'FAIL: '//TRIM(testname)//'WRFU_TimeGet() ', &
2706 CALL adjust_io_timestr ( TI, CT, ST, computed_str )
2708 test_passed = .FALSE.
2709 IF ( LEN_TRIM(res_str) == LEN_TRIM(computed_str) ) THEN
2710 IF ( res_str(1:LEN_TRIM(res_str)) == computed_str(1:LEN_TRIM(computed_str)) ) THEN
2711 test_passed = .TRUE.
2715 IF ( test_passed ) THEN
2716 WRITE(*,FMT='(A)') 'PASS: '//TRIM(testname)
2718 WRITE(*,*) 'FAIL: ',TRIM(testname),': adjust_io_timestr(', &
2719 TRIM(TI_str),',',TRIM(CT_str),',',TRIM(ST_str),') expected <', &
2720 TRIM(res_str),'> but computed <',TRIM(computed_str),'>'
2722 END SUBROUTINE test_adjust_io_timestr
2724 ! Print lots of time-related information for testing and debugging.
2725 ! Printed lines include pre_str and special string DOMAIN_TIME_TEST
2726 ! suitable for grepping by test scripts.
2727 ! Returns immediately unless self_test_domain has been set to .true. in
2728 ! namelist /time_control/ .
2729 SUBROUTINE domain_time_test ( grid, pre_str )
2731 TYPE(domain), INTENT(IN) :: grid
2732 CHARACTER (LEN=*), INTENT(IN) :: pre_str
2734 LOGICAL, SAVE :: one_time_tests_done = .FALSE.
2735 REAL :: minutesSinceSimulationStart
2736 INTEGER :: advance_count, rc
2737 REAL :: currentDayOfYearReal
2738 TYPE(WRFU_TimeInterval) :: timeSinceSimulationStart
2739 TYPE(WRFU_Time) :: simulationStartTime
2740 CHARACTER (LEN=512) :: res_str
2741 LOGICAL :: self_test_domain
2743 ! NOTE: test_adjust_io_timestr() (see below) is a self-test that
2744 ! prints PASS/FAIL/ERROR messages in a standard format. All
2745 ! of the other tests should be strucutred the same way,
2748 CALL nl_get_self_test_domain( 1, self_test_domain )
2749 IF ( self_test_domain ) THEN
2750 CALL domain_clock_get( grid, advanceCount=advance_count )
2751 WRITE ( res_str, FMT="(I8.8)" ) advance_count
2752 CALL domain_time_test_print( pre_str, 'advanceCount', res_str )
2753 CALL domain_clock_get( grid, currentDayOfYearReal=currentDayOfYearReal )
2754 WRITE ( res_str, FMT='(F10.6)' ) currentDayOfYearReal
2755 CALL domain_time_test_print( pre_str, 'currentDayOfYearReal', res_str )
2756 CALL domain_clock_get( grid, minutesSinceSimulationStart=minutesSinceSimulationStart )
2757 WRITE ( res_str, FMT='(F10.6)' ) minutesSinceSimulationStart
2758 CALL domain_time_test_print( pre_str, 'minutesSinceSimulationStart', res_str )
2759 CALL domain_clock_get( grid, current_timestr=res_str )
2760 CALL domain_time_test_print( pre_str, 'current_timestr', res_str )
2761 CALL domain_clock_get( grid, current_timestr_frac=res_str )
2762 CALL domain_time_test_print( pre_str, 'current_timestr_frac', res_str )
2763 CALL domain_clock_get( grid, timeSinceSimulationStart=timeSinceSimulationStart )
2764 CALL WRFU_TimeIntervalGet( timeSinceSimulationStart, timeString=res_str, rc=rc )
2765 IF ( rc /= WRFU_SUCCESS ) THEN
2766 CALL wrf_error_fatal ( &
2767 'domain_time_test: WRFU_TimeIntervalGet() failed' )
2769 CALL domain_time_test_print( pre_str, 'timeSinceSimulationStart', res_str )
2770 ! The following tests should only be done once, the first time this
2771 ! routine is called.
2772 IF ( .NOT. one_time_tests_done ) THEN
2773 one_time_tests_done = .TRUE.
2774 CALL domain_clock_get( grid, simulationStartTimeStr=res_str )
2775 CALL domain_time_test_print( pre_str, 'simulationStartTime', res_str )
2776 CALL domain_clock_get( grid, start_timestr=res_str )
2777 CALL domain_time_test_print( pre_str, 'start_timestr', res_str )
2778 CALL domain_clock_get( grid, stop_timestr=res_str )
2779 CALL domain_time_test_print( pre_str, 'stop_timestr', res_str )
2780 CALL domain_clock_get( grid, time_stepstr=res_str )
2781 CALL domain_time_test_print( pre_str, 'time_stepstr', res_str )
2782 CALL domain_clock_get( grid, time_stepstr_frac=res_str )
2783 CALL domain_time_test_print( pre_str, 'time_stepstr_frac', res_str )
2784 ! Test adjust_io_timestr()
2785 ! CT = 2000-01-26_00:00:00 (current time)
2786 ! ST = 2000-01-24_12:00:00 (start time)
2787 ! TI = 00000_03:00:00 (time interval)
2788 ! the resulting time string should be:
2789 ! 2000-01-26_00:00:00
2790 CALL test_adjust_io_timestr( TI_h=3, TI_m=0, TI_s=0, &
2791 CT_yy=2000, CT_mm=1, CT_dd=26, CT_h=0, CT_m=0, CT_s=0, &
2792 ST_yy=2000, ST_mm=1, ST_dd=24, ST_h=12, ST_m=0, ST_s=0, &
2793 res_str='2000-01-26_00:00:00', testname='adjust_io_timestr_1' )
2794 ! this should fail (and does)
2795 ! CALL test_adjust_io_timestr( TI_h=3, TI_m=0, TI_s=0, &
2796 ! CT_yy=2000, CT_mm=1, CT_dd=26, CT_h=0, CT_m=0, CT_s=0, &
2797 ! ST_yy=2000, ST_mm=1, ST_dd=24, ST_h=12, ST_m=0, ST_s=0, &
2798 ! res_str='2000-01-26_00:00:01', testname='adjust_io_timestr_FAIL1' )
2802 END SUBROUTINE domain_time_test
2804 !******************************************************************************
2806 !******************************************************************************
2809 END MODULE module_domain
2812 ! The following routines are outside this module to avoid build dependences.
2815 ! Get current time as a string (current time from clock attached to the
2816 ! current_grid). Includes fractional part, if present.
2817 ! Returns empty string if current_grid is not set or if timing has not yet
2818 ! been set up on current_grid.
2819 SUBROUTINE get_current_time_string( time_str )
2822 CHARACTER (LEN=*), INTENT(OUT) :: time_str
2824 INTEGER :: debug_level_lcl
2825 !PRINT *,'DEBUG: begin get_current_time_string()'
2827 IF ( current_grid_set ) THEN
2829 !PRINT *,'DEBUG: get_current_time_string(): checking association of current_grid...'
2830 !IF ( ASSOCIATED( current_grid ) ) THEN
2831 ! PRINT *,'DEBUG: get_current_time_string(): current_grid is associated'
2833 ! PRINT *,'DEBUG: get_current_time_string(): current_grid is NOT associated'
2836 IF ( current_grid%time_set ) THEN
2837 !PRINT *,'DEBUG: get_current_time_string(): calling domain_clock_get()'
2838 ! set debug_level to zero and clear current_grid_set to avoid recursion
2839 CALL get_wrf_debug_level( debug_level_lcl )
2840 CALL set_wrf_debug_level ( 0 )
2841 current_grid_set = .FALSE.
2842 CALL domain_clock_get( current_grid, current_timestr_frac=time_str )
2843 ! restore debug_level and current_grid_set
2844 CALL set_wrf_debug_level ( debug_level_lcl )
2845 current_grid_set = .TRUE.
2846 !PRINT *,'DEBUG: get_current_time_string(): back from domain_clock_get()'
2849 !PRINT *,'DEBUG: end get_current_time_string()'
2850 END SUBROUTINE get_current_time_string
2853 ! Get current domain name as a string of form "d<NN>" where "<NN>" is
2854 ! grid%id printed in two characters, with leading zero if needed ("d01",
2856 ! Return empty string if current_grid not set.
2857 SUBROUTINE get_current_grid_name( grid_str )
2860 CHARACTER (LEN=*), INTENT(OUT) :: grid_str
2862 IF ( current_grid_set ) THEN
2863 WRITE(grid_str,FMT="('d',I2.2)") current_grid%id
2865 END SUBROUTINE get_current_grid_name
2868 ! moved these outside module domain to avoid circular reference from module_alloc_space which also uses
2870 SUBROUTINE get_ijk_from_grid_ext ( grid , &
2871 ids, ide, jds, jde, kds, kde, &
2872 ims, ime, jms, jme, kms, kme, &
2873 ips, ipe, jps, jpe, kps, kpe, &
2874 imsx, imex, jmsx, jmex, kmsx, kmex, &
2875 ipsx, ipex, jpsx, jpex, kpsx, kpex, &
2876 imsy, imey, jmsy, jmey, kmsy, kmey, &
2877 ipsy, ipey, jpsy, jpey, kpsy, kpey )
2880 TYPE( domain ), INTENT (IN) :: grid
2881 INTEGER, INTENT(OUT) :: &
2882 ids, ide, jds, jde, kds, kde, &
2883 ims, ime, jms, jme, kms, kme, &
2884 ips, ipe, jps, jpe, kps, kpe, &
2885 imsx, imex, jmsx, jmex, kmsx, kmex, &
2886 ipsx, ipex, jpsx, jpex, kpsx, kpex, &
2887 imsy, imey, jmsy, jmey, kmsy, kmey, &
2888 ipsy, ipey, jpsy, jpey, kpsy, kpey
2890 CALL get_ijk_from_grid2 ( grid , &
2891 ids, ide, jds, jde, kds, kde, &
2892 ims, ime, jms, jme, kms, kme, &
2893 ips, ipe, jps, jpe, kps, kpe )
2894 data_ordering : SELECT CASE ( model_data_order )
2895 CASE ( DATA_ORDER_XYZ )
2896 imsx = grid%sm31x ; imex = grid%em31x ; jmsx = grid%sm32x ; jmex = grid%em32x ; kmsx = grid%sm33x ; kmex = grid%em33x ;
2897 ipsx = grid%sp31x ; ipex = grid%ep31x ; jpsx = grid%sp32x ; jpex = grid%ep32x ; kpsx = grid%sp33x ; kpex = grid%ep33x ;
2898 imsy = grid%sm31y ; imey = grid%em31y ; jmsy = grid%sm32y ; jmey = grid%em32y ; kmsy = grid%sm33y ; kmey = grid%em33y ;
2899 ipsy = grid%sp31y ; ipey = grid%ep31y ; jpsy = grid%sp32y ; jpey = grid%ep32y ; kpsy = grid%sp33y ; kpey = grid%ep33y ;
2900 CASE ( DATA_ORDER_YXZ )
2901 imsx = grid%sm32x ; imex = grid%em32x ; jmsx = grid%sm31x ; jmex = grid%em31x ; kmsx = grid%sm33x ; kmex = grid%em33x ;
2902 ipsx = grid%sp32x ; ipex = grid%ep32x ; jpsx = grid%sp31x ; jpex = grid%ep31x ; kpsx = grid%sp33x ; kpex = grid%ep33x ;
2903 imsy = grid%sm32y ; imey = grid%em32y ; jmsy = grid%sm31y ; jmey = grid%em31y ; kmsy = grid%sm33y ; kmey = grid%em33y ;
2904 ipsy = grid%sp32y ; ipey = grid%ep32y ; jpsy = grid%sp31y ; jpey = grid%ep31y ; kpsy = grid%sp33y ; kpey = grid%ep33y ;
2905 CASE ( DATA_ORDER_ZXY )
2906 imsx = grid%sm32x ; imex = grid%em32x ; jmsx = grid%sm33x ; jmex = grid%em33x ; kmsx = grid%sm31x ; kmex = grid%em31x ;
2907 ipsx = grid%sp32x ; ipex = grid%ep32x ; jpsx = grid%sp33x ; jpex = grid%ep33x ; kpsx = grid%sp31x ; kpex = grid%ep31x ;
2908 imsy = grid%sm32y ; imey = grid%em32y ; jmsy = grid%sm33y ; jmey = grid%em33y ; kmsy = grid%sm31y ; kmey = grid%em31y ;
2909 ipsy = grid%sp32y ; ipey = grid%ep32y ; jpsy = grid%sp33y ; jpey = grid%ep33y ; kpsy = grid%sp31y ; kpey = grid%ep31y ;
2910 CASE ( DATA_ORDER_ZYX )
2911 imsx = grid%sm33x ; imex = grid%em33x ; jmsx = grid%sm32x ; jmex = grid%em32x ; kmsx = grid%sm31x ; kmex = grid%em31x ;
2912 ipsx = grid%sp33x ; ipex = grid%ep33x ; jpsx = grid%sp32x ; jpex = grid%ep32x ; kpsx = grid%sp31x ; kpex = grid%ep31x ;
2913 imsy = grid%sm33y ; imey = grid%em33y ; jmsy = grid%sm32y ; jmey = grid%em32y ; kmsy = grid%sm31y ; kmey = grid%em31y ;
2914 ipsy = grid%sp33y ; ipey = grid%ep33y ; jpsy = grid%sp32y ; jpey = grid%ep32y ; kpsy = grid%sp31y ; kpey = grid%ep31y ;
2915 CASE ( DATA_ORDER_XZY )
2916 imsx = grid%sm31x ; imex = grid%em31x ; jmsx = grid%sm33x ; jmex = grid%em33x ; kmsx = grid%sm32x ; kmex = grid%em32x ;
2917 ipsx = grid%sp31x ; ipex = grid%ep31x ; jpsx = grid%sp33x ; jpex = grid%ep33x ; kpsx = grid%sp32x ; kpex = grid%ep32x ;
2918 imsy = grid%sm31y ; imey = grid%em31y ; jmsy = grid%sm33y ; jmey = grid%em33y ; kmsy = grid%sm32y ; kmey = grid%em32y ;
2919 ipsy = grid%sp31y ; ipey = grid%ep31y ; jpsy = grid%sp33y ; jpey = grid%ep33y ; kpsy = grid%sp32y ; kpey = grid%ep32y ;
2920 CASE ( DATA_ORDER_YZX )
2921 imsx = grid%sm33x ; imex = grid%em33x ; jmsx = grid%sm31x ; jmex = grid%em31x ; kmsx = grid%sm32x ; kmex = grid%em32x ;
2922 ipsx = grid%sp33x ; ipex = grid%ep33x ; jpsx = grid%sp31x ; jpex = grid%ep31x ; kpsx = grid%sp32x ; kpex = grid%ep32x ;
2923 imsy = grid%sm33y ; imey = grid%em33y ; jmsy = grid%sm31y ; jmey = grid%em31y ; kmsy = grid%sm32y ; kmey = grid%em32y ;
2924 ipsy = grid%sp33y ; ipey = grid%ep33y ; jpsy = grid%sp31y ; jpey = grid%ep31y ; kpsy = grid%sp32y ; kpey = grid%ep32y ;
2925 END SELECT data_ordering
2926 END SUBROUTINE get_ijk_from_grid_ext
2928 ! return the values for subgrid whose refinement is in grid%sr
2929 ! note when using this routine, it does not affect K. For K
2930 ! (vertical), it just returns what get_ijk_from_grid does
2931 SUBROUTINE get_ijk_from_subgrid_ext ( grid , &
2932 ids0, ide0, jds0, jde0, kds0, kde0, &
2933 ims0, ime0, jms0, jme0, kms0, kme0, &
2934 ips0, ipe0, jps0, jpe0, kps0, kpe0 )
2937 TYPE( domain ), INTENT (IN) :: grid
2938 INTEGER, INTENT(OUT) :: &
2939 ids0, ide0, jds0, jde0, kds0, kde0, &
2940 ims0, ime0, jms0, jme0, kms0, kme0, &
2941 ips0, ipe0, jps0, jpe0, kps0, kpe0
2944 ids, ide, jds, jde, kds, kde, &
2945 ims, ime, jms, jme, kms, kme, &
2946 ips, ipe, jps, jpe, kps, kpe
2947 CALL get_ijk_from_grid ( grid , &
2948 ids, ide, jds, jde, kds, kde, &
2949 ims, ime, jms, jme, kms, kme, &
2950 ips, ipe, jps, jpe, kps, kpe )
2952 ide0 = ide * grid%sr_x
2953 ims0 = (ims-1)*grid%sr_x+1
2954 ime0 = ime * grid%sr_x
2955 ips0 = (ips-1)*grid%sr_x+1
2956 ipe0 = ipe * grid%sr_x
2959 jde0 = jde * grid%sr_y
2960 jms0 = (jms-1)*grid%sr_y+1
2961 jme0 = jme * grid%sr_y
2962 jps0 = (jps-1)*grid%sr_y+1
2963 jpe0 = jpe * grid%sr_y
2972 END SUBROUTINE get_ijk_from_subgrid_ext
2974 ! find the grid based on the id reference and return that
2975 SUBROUTINE get_dims_from_grid_id ( id &
2983 USE module_domain, ONLY : domain, head_grid, find_grid_by_id
2985 TYPE( domain ), POINTER :: grid
2986 INTEGER, INTENT(IN ) :: id
2987 INTEGER, DIMENSION(3), INTENT(INOUT) :: &
3000 CALL find_grid_by_id ( id, head_grid, grid )
3002 IF ( ASSOCIATED(grid) ) THEN
3003 ds(1) = grid%sd31 ; de(1) = grid%ed31 ; ds(2) = grid%sd32 ; de(2) = grid%ed32 ; ds(3) = grid%sd33 ; de(3) = grid%ed33 ;
3004 ms(1) = grid%sm31 ; me(1) = grid%em31 ; ms(2) = grid%sm32 ; me(2) = grid%em32 ; ms(3) = grid%sm33 ; me(3) = grid%em33 ;
3005 ps(1) = grid%sp31 ; pe(1) = grid%ep31 ; ps(2) = grid%sp32 ; pe(2) = grid%ep32 ; ps(3) = grid%sp33 ; pe(3) = grid%ep33 ;
3006 mxs(1) = grid%sm31x ; mxe(1) = grid%em31x
3007 mxs(2) = grid%sm32x ; mxe(2) = grid%em32x
3008 mxs(3) = grid%sm33x ; mxe(3) = grid%em33x
3009 pxs(1) = grid%sp31x ; pxe(1) = grid%ep31x
3010 pxs(2) = grid%sp32x ; pxe(2) = grid%ep32x
3011 pxs(3) = grid%sp33x ; pxe(3) = grid%ep33x
3012 mys(1) = grid%sm31y ; mye(1) = grid%em31y
3013 mys(2) = grid%sm32y ; mye(2) = grid%em32y
3014 mys(3) = grid%sm33y ; mye(3) = grid%em33y
3015 pys(1) = grid%sp31y ; pye(1) = grid%ep31y
3016 pys(2) = grid%sp32y ; pye(2) = grid%ep32y
3017 pys(3) = grid%sp33y ; pye(3) = grid%ep33y
3019 WRITE(mess,*)'internal error: get_ijk_from_grid_id: no such grid id:',id
3020 CALL wrf_error_fatal(TRIM(mess))
3023 END SUBROUTINE get_dims_from_grid_id
3025 ! find the grid based on the id reference and return that
3026 SUBROUTINE get_ijk_from_grid_id ( id , &
3027 ids, ide, jds, jde, kds, kde, &
3028 ims, ime, jms, jme, kms, kme, &
3029 ips, ipe, jps, jpe, kps, kpe, &
3030 imsx, imex, jmsx, jmex, kmsx, kmex, &
3031 ipsx, ipex, jpsx, jpex, kpsx, kpex, &
3032 imsy, imey, jmsy, jmey, kmsy, kmey, &
3033 ipsy, ipey, jpsy, jpey, kpsy, kpey )
3034 USE module_domain, ONLY : domain, head_grid, find_grid_by_id, get_ijk_from_grid
3036 TYPE( domain ), POINTER :: grid
3037 INTEGER, INTENT(IN ) :: id
3038 INTEGER, INTENT(OUT) :: &
3039 ids, ide, jds, jde, kds, kde, &
3040 ims, ime, jms, jme, kms, kme, &
3041 ips, ipe, jps, jpe, kps, kpe, &
3042 imsx, imex, jmsx, jmex, kmsx, kmex, &
3043 ipsx, ipex, jpsx, jpex, kpsx, kpex, &
3044 imsy, imey, jmsy, jmey, kmsy, kmey, &
3045 ipsy, ipey, jpsy, jpey, kpsy, kpey
3050 CALL find_grid_by_id ( id, head_grid, grid )
3052 IF ( ASSOCIATED(grid) ) THEN
3053 CALL get_ijk_from_grid ( grid , &
3054 ids, ide, jds, jde, kds, kde, &
3055 ims, ime, jms, jme, kms, kme, &
3056 ips, ipe, jps, jpe, kps, kpe, &
3057 imsx, imex, jmsx, jmex, kmsx, kmex, &
3058 ipsx, ipex, jpsx, jpex, kpsx, kpex, &
3059 imsy, imey, jmsy, jmey, kmsy, kmey, &
3060 ipsy, ipey, jpsy, jpey, kpsy, kpey )
3062 WRITE(mess,*)'internal error: get_ijk_from_grid_id: no such grid id:',id
3063 CALL wrf_error_fatal(TRIM(mess))
3066 END SUBROUTINE get_ijk_from_grid_id
3068 ! version of this routine that can be called from set_scalar_indices_from_config in
3069 ! module_configure, which can not USE module_domain without creating a circular use assocaition
3070 SUBROUTINE modify_io_masks ( id )
3071 USE module_domain, ONLY : domain, modify_io_masks1, head_grid, find_grid_by_id
3073 INTEGER, INTENT(IN) :: id
3074 TYPE(domain), POINTER :: grid
3075 CALL find_grid_by_id( id, head_grid, grid )
3076 IF ( ASSOCIATED( grid ) ) CALL modify_io_masks1( grid, id )
3078 END SUBROUTINE modify_io_masks