PageRenderTime 52ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 1ms

/wrfv2_fire/frame/module_domain.F

https://github.com/jbeezley/wrf-fire
FORTRAN Legacy | 2991 lines | 1853 code | 300 blank | 838 comment | 9 complexity | 53f37e7c7f8d2d3bdfec4dc967189278 MD5 | raw file
Possible License(s): AGPL-1.0
  1. !WRF:DRIVER_LAYER:DOMAIN_OBJECT
  2. !
  3. ! Following are the routines contained within this MODULE:
  4. ! alloc_and_configure_domain 1. Allocate the space for a single domain (constants
  5. ! and null terminate pointers).
  6. ! 2. Connect the domains as a linked list.
  7. ! 3. Store all of the domain constants.
  8. ! 4. CALL alloc_space_field.
  9. ! alloc_space_field 1. Allocate space for the gridded data required for
  10. ! each domain.
  11. ! dealloc_space_domain 1. Reconnect linked list nodes since the current
  12. ! node is removed.
  13. ! 2. CALL dealloc_space_field.
  14. ! 3. Deallocate single domain.
  15. ! dealloc_space_field 1. Deallocate each of the fields for a particular
  16. ! domain.
  17. ! first_loc_integer 1. Find the first incidence of a particular
  18. ! domain identifier from an array of domain
  19. ! identifiers.
  20. MODULE module_domain
  21. USE module_driver_constants
  22. USE module_machine
  23. USE module_configure
  24. USE module_wrf_error
  25. USE module_utility
  26. USE module_domain_type
  27. ! In WRFV3, the module_domain_type is defined
  28. ! in a separaate source file, frame/module_domain_type.F
  29. ! This enables splitting off the alloc_space_field routine
  30. ! into a separate file, reducing the size of module_domain
  31. ! Now that a "domain" TYPE exists, we can use it to store a few pointers
  32. ! to this type. These are primarily for use in traversing the linked list.
  33. ! The "head_grid" is always the pointer to the first domain that is
  34. ! allocated. This is available and is not to be changed. The others are
  35. ! just temporary pointers.
  36. TYPE(domain) , POINTER :: head_grid , new_grid , next_grid , old_grid
  37. ! To facilitate an easy integration of each of the domains that are on the
  38. ! same level, we have an array for the head pointer for each level. This
  39. ! removed the need to search through the linked list at each time step to
  40. ! find which domains are to be active.
  41. TYPE domain_levels
  42. TYPE(domain) , POINTER :: first_domain
  43. END TYPE domain_levels
  44. TYPE(domain_levels) , DIMENSION(max_levels) :: head_for_each_level
  45. ! Use this to support debugging features, giving easy access to clock, etc.
  46. TYPE(domain), POINTER :: current_grid
  47. LOGICAL, SAVE :: current_grid_set = .FALSE.
  48. ! internal routines
  49. PRIVATE domain_time_test_print
  50. PRIVATE test_adjust_io_timestr
  51. INTERFACE get_ijk_from_grid
  52. MODULE PROCEDURE get_ijk_from_grid1, get_ijk_from_grid2
  53. END INTERFACE
  54. INTEGER, PARAMETER :: max_hst_mods = 200
  55. CONTAINS
  56. SUBROUTINE adjust_domain_dims_for_move( grid , dx, dy )
  57. IMPLICIT NONE
  58. TYPE( domain ), POINTER :: grid
  59. INTEGER, INTENT(IN) :: dx, dy
  60. data_ordering : SELECT CASE ( model_data_order )
  61. CASE ( DATA_ORDER_XYZ )
  62. grid%sm31 = grid%sm31 + dx
  63. grid%em31 = grid%em31 + dx
  64. grid%sm32 = grid%sm32 + dy
  65. grid%em32 = grid%em32 + dy
  66. grid%sp31 = grid%sp31 + dx
  67. grid%ep31 = grid%ep31 + dx
  68. grid%sp32 = grid%sp32 + dy
  69. grid%ep32 = grid%ep32 + dy
  70. grid%sd31 = grid%sd31 + dx
  71. grid%ed31 = grid%ed31 + dx
  72. grid%sd32 = grid%sd32 + dy
  73. grid%ed32 = grid%ed32 + dy
  74. CASE ( DATA_ORDER_YXZ )
  75. grid%sm31 = grid%sm31 + dy
  76. grid%em31 = grid%em31 + dy
  77. grid%sm32 = grid%sm32 + dx
  78. grid%em32 = grid%em32 + dx
  79. grid%sp31 = grid%sp31 + dy
  80. grid%ep31 = grid%ep31 + dy
  81. grid%sp32 = grid%sp32 + dx
  82. grid%ep32 = grid%ep32 + dx
  83. grid%sd31 = grid%sd31 + dy
  84. grid%ed31 = grid%ed31 + dy
  85. grid%sd32 = grid%sd32 + dx
  86. grid%ed32 = grid%ed32 + dx
  87. CASE ( DATA_ORDER_ZXY )
  88. grid%sm32 = grid%sm32 + dx
  89. grid%em32 = grid%em32 + dx
  90. grid%sm33 = grid%sm33 + dy
  91. grid%em33 = grid%em33 + dy
  92. grid%sp32 = grid%sp32 + dx
  93. grid%ep32 = grid%ep32 + dx
  94. grid%sp33 = grid%sp33 + dy
  95. grid%ep33 = grid%ep33 + dy
  96. grid%sd32 = grid%sd32 + dx
  97. grid%ed32 = grid%ed32 + dx
  98. grid%sd33 = grid%sd33 + dy
  99. grid%ed33 = grid%ed33 + dy
  100. CASE ( DATA_ORDER_ZYX )
  101. grid%sm32 = grid%sm32 + dy
  102. grid%em32 = grid%em32 + dy
  103. grid%sm33 = grid%sm33 + dx
  104. grid%em33 = grid%em33 + dx
  105. grid%sp32 = grid%sp32 + dy
  106. grid%ep32 = grid%ep32 + dy
  107. grid%sp33 = grid%sp33 + dx
  108. grid%ep33 = grid%ep33 + dx
  109. grid%sd32 = grid%sd32 + dy
  110. grid%ed32 = grid%ed32 + dy
  111. grid%sd33 = grid%sd33 + dx
  112. grid%ed33 = grid%ed33 + dx
  113. CASE ( DATA_ORDER_XZY )
  114. grid%sm31 = grid%sm31 + dx
  115. grid%em31 = grid%em31 + dx
  116. grid%sm33 = grid%sm33 + dy
  117. grid%em33 = grid%em33 + dy
  118. grid%sp31 = grid%sp31 + dx
  119. grid%ep31 = grid%ep31 + dx
  120. grid%sp33 = grid%sp33 + dy
  121. grid%ep33 = grid%ep33 + dy
  122. grid%sd31 = grid%sd31 + dx
  123. grid%ed31 = grid%ed31 + dx
  124. grid%sd33 = grid%sd33 + dy
  125. grid%ed33 = grid%ed33 + dy
  126. CASE ( DATA_ORDER_YZX )
  127. grid%sm31 = grid%sm31 + dy
  128. grid%em31 = grid%em31 + dy
  129. grid%sm33 = grid%sm33 + dx
  130. grid%em33 = grid%em33 + dx
  131. grid%sp31 = grid%sp31 + dy
  132. grid%ep31 = grid%ep31 + dy
  133. grid%sp33 = grid%sp33 + dx
  134. grid%ep33 = grid%ep33 + dx
  135. grid%sd31 = grid%sd31 + dy
  136. grid%ed31 = grid%ed31 + dy
  137. grid%sd33 = grid%sd33 + dx
  138. grid%ed33 = grid%ed33 + dx
  139. END SELECT data_ordering
  140. #if 0
  141. CALL dealloc_space_field ( grid )
  142. CALL alloc_space_field ( grid, grid%id , 1 , 2 , .FALSE. , &
  143. grid%sd31, grid%ed31, grid%sd32, grid%ed32, grid%sd33, grid%ed33, &
  144. grid%sm31, grid%em31, grid%sm32, grid%em32, grid%sm33, grid%em33, &
  145. grid%sp31, grid%ep31, grid%sp32, grid%ep32, grid%sp33, grid%ep33, &
  146. grid%sp31x, grid%ep31x, grid%sp32x, grid%ep32x, grid%sp33x, grid%ep33x, &
  147. grid%sp31y, grid%ep31y, grid%sp32y, grid%ep32y, grid%sp33y, grid%ep33y, &
  148. grid%sm31x, grid%em31x, grid%sm32x, grid%em32x, grid%sm33x, grid%em33x, & ! x-xpose
  149. grid%sm31y, grid%em31y, grid%sm32y, grid%em32y, grid%sm33y, grid%em33y & ! y-xpose
  150. )
  151. #endif
  152. RETURN
  153. END SUBROUTINE adjust_domain_dims_for_move
  154. #if 1
  155. SUBROUTINE get_ijk_from_grid1 ( grid , &
  156. ids, ide, jds, jde, kds, kde, &
  157. ims, ime, jms, jme, kms, kme, &
  158. ips, ipe, jps, jpe, kps, kpe, &
  159. imsx, imex, jmsx, jmex, kmsx, kmex, &
  160. ipsx, ipex, jpsx, jpex, kpsx, kpex, &
  161. imsy, imey, jmsy, jmey, kmsy, kmey, &
  162. ipsy, ipey, jpsy, jpey, kpsy, kpey )
  163. IMPLICIT NONE
  164. TYPE( domain ), INTENT (IN) :: grid
  165. INTEGER, INTENT(OUT) :: &
  166. ids, ide, jds, jde, kds, kde, &
  167. ims, ime, jms, jme, kms, kme, &
  168. ips, ipe, jps, jpe, kps, kpe, &
  169. imsx, imex, jmsx, jmex, kmsx, kmex, &
  170. ipsx, ipex, jpsx, jpex, kpsx, kpex, &
  171. imsy, imey, jmsy, jmey, kmsy, kmey, &
  172. ipsy, ipey, jpsy, jpey, kpsy, kpey
  173. CALL get_ijk_from_grid2 ( grid , &
  174. ids, ide, jds, jde, kds, kde, &
  175. ims, ime, jms, jme, kms, kme, &
  176. ips, ipe, jps, jpe, kps, kpe )
  177. data_ordering : SELECT CASE ( model_data_order )
  178. CASE ( DATA_ORDER_XYZ )
  179. imsx = grid%sm31x ; imex = grid%em31x ; jmsx = grid%sm32x ; jmex = grid%em32x ; kmsx = grid%sm33x ; kmex = grid%em33x ;
  180. ipsx = grid%sp31x ; ipex = grid%ep31x ; jpsx = grid%sp32x ; jpex = grid%ep32x ; kpsx = grid%sp33x ; kpex = grid%ep33x ;
  181. imsy = grid%sm31y ; imey = grid%em31y ; jmsy = grid%sm32y ; jmey = grid%em32y ; kmsy = grid%sm33y ; kmey = grid%em33y ;
  182. ipsy = grid%sp31y ; ipey = grid%ep31y ; jpsy = grid%sp32y ; jpey = grid%ep32y ; kpsy = grid%sp33y ; kpey = grid%ep33y ;
  183. CASE ( DATA_ORDER_YXZ )
  184. imsx = grid%sm32x ; imex = grid%em32x ; jmsx = grid%sm31x ; jmex = grid%em31x ; kmsx = grid%sm33x ; kmex = grid%em33x ;
  185. ipsx = grid%sp32x ; ipex = grid%ep32x ; jpsx = grid%sp31x ; jpex = grid%ep31x ; kpsx = grid%sp33x ; kpex = grid%ep33x ;
  186. imsy = grid%sm32y ; imey = grid%em32y ; jmsy = grid%sm31y ; jmey = grid%em31y ; kmsy = grid%sm33y ; kmey = grid%em33y ;
  187. ipsy = grid%sp32y ; ipey = grid%ep32y ; jpsy = grid%sp31y ; jpey = grid%ep31y ; kpsy = grid%sp33y ; kpey = grid%ep33y ;
  188. CASE ( DATA_ORDER_ZXY )
  189. imsx = grid%sm32x ; imex = grid%em32x ; jmsx = grid%sm33x ; jmex = grid%em33x ; kmsx = grid%sm31x ; kmex = grid%em31x ;
  190. ipsx = grid%sp32x ; ipex = grid%ep32x ; jpsx = grid%sp33x ; jpex = grid%ep33x ; kpsx = grid%sp31x ; kpex = grid%ep31x ;
  191. imsy = grid%sm32y ; imey = grid%em32y ; jmsy = grid%sm33y ; jmey = grid%em33y ; kmsy = grid%sm31y ; kmey = grid%em31y ;
  192. ipsy = grid%sp32y ; ipey = grid%ep32y ; jpsy = grid%sp33y ; jpey = grid%ep33y ; kpsy = grid%sp31y ; kpey = grid%ep31y ;
  193. CASE ( DATA_ORDER_ZYX )
  194. imsx = grid%sm33x ; imex = grid%em33x ; jmsx = grid%sm32x ; jmex = grid%em32x ; kmsx = grid%sm31x ; kmex = grid%em31x ;
  195. ipsx = grid%sp33x ; ipex = grid%ep33x ; jpsx = grid%sp32x ; jpex = grid%ep32x ; kpsx = grid%sp31x ; kpex = grid%ep31x ;
  196. imsy = grid%sm33y ; imey = grid%em33y ; jmsy = grid%sm32y ; jmey = grid%em32y ; kmsy = grid%sm31y ; kmey = grid%em31y ;
  197. ipsy = grid%sp33y ; ipey = grid%ep33y ; jpsy = grid%sp32y ; jpey = grid%ep32y ; kpsy = grid%sp31y ; kpey = grid%ep31y ;
  198. CASE ( DATA_ORDER_XZY )
  199. imsx = grid%sm31x ; imex = grid%em31x ; jmsx = grid%sm33x ; jmex = grid%em33x ; kmsx = grid%sm32x ; kmex = grid%em32x ;
  200. ipsx = grid%sp31x ; ipex = grid%ep31x ; jpsx = grid%sp33x ; jpex = grid%ep33x ; kpsx = grid%sp32x ; kpex = grid%ep32x ;
  201. imsy = grid%sm31y ; imey = grid%em31y ; jmsy = grid%sm33y ; jmey = grid%em33y ; kmsy = grid%sm32y ; kmey = grid%em32y ;
  202. ipsy = grid%sp31y ; ipey = grid%ep31y ; jpsy = grid%sp33y ; jpey = grid%ep33y ; kpsy = grid%sp32y ; kpey = grid%ep32y ;
  203. CASE ( DATA_ORDER_YZX )
  204. imsx = grid%sm33x ; imex = grid%em33x ; jmsx = grid%sm31x ; jmex = grid%em31x ; kmsx = grid%sm32x ; kmex = grid%em32x ;
  205. ipsx = grid%sp33x ; ipex = grid%ep33x ; jpsx = grid%sp31x ; jpex = grid%ep31x ; kpsx = grid%sp32x ; kpex = grid%ep32x ;
  206. imsy = grid%sm33y ; imey = grid%em33y ; jmsy = grid%sm31y ; jmey = grid%em31y ; kmsy = grid%sm32y ; kmey = grid%em32y ;
  207. ipsy = grid%sp33y ; ipey = grid%ep33y ; jpsy = grid%sp31y ; jpey = grid%ep31y ; kpsy = grid%sp32y ; kpey = grid%ep32y ;
  208. END SELECT data_ordering
  209. END SUBROUTINE get_ijk_from_grid1
  210. SUBROUTINE get_ijk_from_grid2 ( grid , &
  211. ids, ide, jds, jde, kds, kde, &
  212. ims, ime, jms, jme, kms, kme, &
  213. ips, ipe, jps, jpe, kps, kpe )
  214. IMPLICIT NONE
  215. TYPE( domain ), INTENT (IN) :: grid
  216. INTEGER, INTENT(OUT) :: &
  217. ids, ide, jds, jde, kds, kde, &
  218. ims, ime, jms, jme, kms, kme, &
  219. ips, ipe, jps, jpe, kps, kpe
  220. data_ordering : SELECT CASE ( model_data_order )
  221. CASE ( DATA_ORDER_XYZ )
  222. ids = grid%sd31 ; ide = grid%ed31 ; jds = grid%sd32 ; jde = grid%ed32 ; kds = grid%sd33 ; kde = grid%ed33 ;
  223. ims = grid%sm31 ; ime = grid%em31 ; jms = grid%sm32 ; jme = grid%em32 ; kms = grid%sm33 ; kme = grid%em33 ;
  224. ips = grid%sp31 ; ipe = grid%ep31 ; jps = grid%sp32 ; jpe = grid%ep32 ; kps = grid%sp33 ; kpe = grid%ep33 ;
  225. CASE ( DATA_ORDER_YXZ )
  226. ids = grid%sd32 ; ide = grid%ed32 ; jds = grid%sd31 ; jde = grid%ed31 ; kds = grid%sd33 ; kde = grid%ed33 ;
  227. ims = grid%sm32 ; ime = grid%em32 ; jms = grid%sm31 ; jme = grid%em31 ; kms = grid%sm33 ; kme = grid%em33 ;
  228. ips = grid%sp32 ; ipe = grid%ep32 ; jps = grid%sp31 ; jpe = grid%ep31 ; kps = grid%sp33 ; kpe = grid%ep33 ;
  229. CASE ( DATA_ORDER_ZXY )
  230. ids = grid%sd32 ; ide = grid%ed32 ; jds = grid%sd33 ; jde = grid%ed33 ; kds = grid%sd31 ; kde = grid%ed31 ;
  231. ims = grid%sm32 ; ime = grid%em32 ; jms = grid%sm33 ; jme = grid%em33 ; kms = grid%sm31 ; kme = grid%em31 ;
  232. ips = grid%sp32 ; ipe = grid%ep32 ; jps = grid%sp33 ; jpe = grid%ep33 ; kps = grid%sp31 ; kpe = grid%ep31 ;
  233. CASE ( DATA_ORDER_ZYX )
  234. ids = grid%sd33 ; ide = grid%ed33 ; jds = grid%sd32 ; jde = grid%ed32 ; kds = grid%sd31 ; kde = grid%ed31 ;
  235. ims = grid%sm33 ; ime = grid%em33 ; jms = grid%sm32 ; jme = grid%em32 ; kms = grid%sm31 ; kme = grid%em31 ;
  236. ips = grid%sp33 ; ipe = grid%ep33 ; jps = grid%sp32 ; jpe = grid%ep32 ; kps = grid%sp31 ; kpe = grid%ep31 ;
  237. CASE ( DATA_ORDER_XZY )
  238. ids = grid%sd31 ; ide = grid%ed31 ; jds = grid%sd33 ; jde = grid%ed33 ; kds = grid%sd32 ; kde = grid%ed32 ;
  239. ims = grid%sm31 ; ime = grid%em31 ; jms = grid%sm33 ; jme = grid%em33 ; kms = grid%sm32 ; kme = grid%em32 ;
  240. ips = grid%sp31 ; ipe = grid%ep31 ; jps = grid%sp33 ; jpe = grid%ep33 ; kps = grid%sp32 ; kpe = grid%ep32 ;
  241. CASE ( DATA_ORDER_YZX )
  242. ids = grid%sd33 ; ide = grid%ed33 ; jds = grid%sd31 ; jde = grid%ed31 ; kds = grid%sd32 ; kde = grid%ed32 ;
  243. ims = grid%sm33 ; ime = grid%em33 ; jms = grid%sm31 ; jme = grid%em31 ; kms = grid%sm32 ; kme = grid%em32 ;
  244. ips = grid%sp33 ; ipe = grid%ep33 ; jps = grid%sp31 ; jpe = grid%ep31 ; kps = grid%sp32 ; kpe = grid%ep32 ;
  245. END SELECT data_ordering
  246. END SUBROUTINE get_ijk_from_grid2
  247. ! return the values for subgrid whose refinement is in grid%sr
  248. ! note when using this routine, it does not affect K. For K
  249. ! (vertical), it just returns what get_ijk_from_grid does
  250. SUBROUTINE get_ijk_from_subgrid ( grid , &
  251. ids0, ide0, jds0, jde0, kds0, kde0, &
  252. ims0, ime0, jms0, jme0, kms0, kme0, &
  253. ips0, ipe0, jps0, jpe0, kps0, kpe0 )
  254. TYPE( domain ), INTENT (IN) :: grid
  255. INTEGER, INTENT(OUT) :: &
  256. ids0, ide0, jds0, jde0, kds0, kde0, &
  257. ims0, ime0, jms0, jme0, kms0, kme0, &
  258. ips0, ipe0, jps0, jpe0, kps0, kpe0
  259. ! Local
  260. INTEGER :: &
  261. ids, ide, jds, jde, kds, kde, &
  262. ims, ime, jms, jme, kms, kme, &
  263. ips, ipe, jps, jpe, kps, kpe
  264. CALL get_ijk_from_grid ( grid , &
  265. ids, ide, jds, jde, kds, kde, &
  266. ims, ime, jms, jme, kms, kme, &
  267. ips, ipe, jps, jpe, kps, kpe )
  268. ids0 = ids
  269. ide0 = ide * grid%sr_x
  270. ims0 = (ims-1)*grid%sr_x+1
  271. ime0 = ime * grid%sr_x
  272. ips0 = (ips-1)*grid%sr_x+1
  273. ipe0 = ipe * grid%sr_x
  274. jds0 = jds
  275. jde0 = jde * grid%sr_y
  276. jms0 = (jms-1)*grid%sr_y+1
  277. jme0 = jme * grid%sr_y
  278. jps0 = (jps-1)*grid%sr_y+1
  279. jpe0 = jpe * grid%sr_y
  280. kds0 = kds
  281. kde0 = kde
  282. kms0 = kms
  283. kme0 = kme
  284. kps0 = kps
  285. kpe0 = kpe
  286. RETURN
  287. END SUBROUTINE get_ijk_from_subgrid
  288. #endif
  289. ! Default version ; Otherwise module containing interface to DM library will provide
  290. SUBROUTINE wrf_patch_domain( id , domdesc , parent, parent_id , parent_domdesc , &
  291. sd1 , ed1 , sp1 , ep1 , sm1 , em1 , &
  292. sd2 , ed2 , sp2 , ep2 , sm2 , em2 , &
  293. sd3 , ed3 , sp3 , ep3 , sm3 , em3 , &
  294. sp1x , ep1x , sm1x , em1x , &
  295. sp2x , ep2x , sm2x , em2x , &
  296. sp3x , ep3x , sm3x , em3x , &
  297. sp1y , ep1y , sm1y , em1y , &
  298. sp2y , ep2y , sm2y , em2y , &
  299. sp3y , ep3y , sm3y , em3y , &
  300. bdx , bdy , bdy_mask )
  301. !<DESCRIPTION>
  302. ! Wrf_patch_domain is called as part of the process of initiating a new
  303. ! domain. Based on the global domain dimension information that is
  304. ! passed in it computes the patch and memory dimensions on this
  305. ! distributed-memory process for parallel compilation when DM_PARALLEL is
  306. ! defined in configure.wrf. In this case, it relies on an external
  307. ! communications package-contributed routine, wrf_dm_patch_domain. For
  308. ! non-parallel compiles, it returns the patch and memory dimensions based
  309. ! on the entire domain. In either case, the memory dimensions will be
  310. ! larger than the patch dimensions, since they allow for distributed
  311. ! memory halo regions (DM_PARALLEL only) and for boundary regions around
  312. ! the domain (used for idealized cases only). The width of the boundary
  313. ! regions to be accommodated is passed in as bdx and bdy.
  314. !
  315. ! The bdy_mask argument is a four-dimensional logical array, each element
  316. ! of which is set to true for any boundaries that this process's patch
  317. ! contains (all four are true in the non-DM_PARALLEL case) and false
  318. ! otherwise. The indices into the bdy_mask are defined in
  319. ! frame/module_state_description.F. P_XSB corresponds boundary that
  320. ! exists at the beginning of the X-dimension; ie. the western boundary;
  321. ! P_XEB to the boundary that corresponds to the end of the X-dimension
  322. ! (east). Likewise for Y (south and north respectively).
  323. !
  324. ! The correspondence of the first, second, and third dimension of each
  325. ! set (domain, memory, and patch) with the coordinate axes of the model
  326. ! domain is based on the setting of the variable model_data_order, which
  327. ! comes into this routine through USE association of
  328. ! module_driver_constants in the enclosing module of this routine,
  329. ! module_domain. Model_data_order is defined by the Registry, based on
  330. ! the dimspec entries which associate dimension specifiers (e.g. 'k') in
  331. ! the Registry with a coordinate axis and specify which dimension of the
  332. ! arrays they represent. For WRF, the sd1 , ed1 , sp1 , ep1 , sm1 , and
  333. ! em1 correspond to the starts and ends of the global, patch, and memory
  334. ! dimensions in X; those with 2 specify Z (vertical); and those with 3
  335. ! specify Y. Note that the WRF convention is to overdimension to allow
  336. ! for staggered fields so that sd<em>n</em>:ed<em>n</em> are the starts
  337. ! and ends of the staggered domains in X. The non-staggered grid runs
  338. ! sd<em>n</em>:ed<em>n</em>-1. The extra row or column on the north or
  339. ! east boundaries is not used for non-staggered fields.
  340. !
  341. ! The domdesc and parent_domdesc arguments are for external communication
  342. ! packages (e.g. RSL) that establish and return to WRF integer handles
  343. ! for referring to operations on domains. These descriptors are not set
  344. ! or used otherwise and they are opaque, which means they are never
  345. ! accessed or modified in WRF; they are only only passed between calls to
  346. ! the external package.
  347. !</DESCRIPTION>
  348. USE module_machine
  349. IMPLICIT NONE
  350. LOGICAL, DIMENSION(4), INTENT(OUT) :: bdy_mask
  351. INTEGER, INTENT(IN) :: sd1 , ed1 , sd2 , ed2 , sd3 , ed3 , bdx , bdy
  352. INTEGER, INTENT(OUT) :: sp1 , ep1 , sp2 , ep2 , sp3 , ep3 , & ! z-xpose (std)
  353. sm1 , em1 , sm2 , em2 , sm3 , em3
  354. INTEGER, INTENT(OUT) :: sp1x , ep1x , sp2x , ep2x , sp3x , ep3x , & ! x-xpose
  355. sm1x , em1x , sm2x , em2x , sm3x , em3x
  356. INTEGER, INTENT(OUT) :: sp1y , ep1y , sp2y , ep2y , sp3y , ep3y , & ! y-xpose
  357. sm1y , em1y , sm2y , em2y , sm3y , em3y
  358. INTEGER, INTENT(IN) :: id , parent_id , parent_domdesc
  359. INTEGER, INTENT(INOUT) :: domdesc
  360. TYPE(domain), POINTER :: parent
  361. !local data
  362. INTEGER spec_bdy_width
  363. CALL nl_get_spec_bdy_width( 1, spec_bdy_width )
  364. #ifndef DM_PARALLEL
  365. bdy_mask = .true. ! only one processor so all 4 boundaries are there
  366. ! this is a trivial version -- 1 patch per processor;
  367. ! use version in module_dm to compute for DM
  368. sp1 = sd1 ; sp2 = sd2 ; sp3 = sd3
  369. ep1 = ed1 ; ep2 = ed2 ; ep3 = ed3
  370. SELECT CASE ( model_data_order )
  371. CASE ( DATA_ORDER_XYZ )
  372. sm1 = sp1 - bdx ; em1 = ep1 + bdx
  373. sm2 = sp2 - bdy ; em2 = ep2 + bdy
  374. sm3 = sp3 ; em3 = ep3
  375. CASE ( DATA_ORDER_YXZ )
  376. sm1 = sp1 - bdy ; em1 = ep1 + bdy
  377. sm2 = sp2 - bdx ; em2 = ep2 + bdx
  378. sm3 = sp3 ; em3 = ep3
  379. CASE ( DATA_ORDER_ZXY )
  380. sm1 = sp1 ; em1 = ep1
  381. sm2 = sp2 - bdx ; em2 = ep2 + bdx
  382. sm3 = sp3 - bdy ; em3 = ep3 + bdy
  383. CASE ( DATA_ORDER_ZYX )
  384. sm1 = sp1 ; em1 = ep1
  385. sm2 = sp2 - bdy ; em2 = ep2 + bdy
  386. sm3 = sp3 - bdx ; em3 = ep3 + bdx
  387. CASE ( DATA_ORDER_XZY )
  388. sm1 = sp1 - bdx ; em1 = ep1 + bdx
  389. sm2 = sp2 ; em2 = ep2
  390. sm3 = sp3 - bdy ; em3 = ep3 + bdy
  391. CASE ( DATA_ORDER_YZX )
  392. sm1 = sp1 - bdy ; em1 = ep1 + bdy
  393. sm2 = sp2 ; em2 = ep2
  394. sm3 = sp3 - bdx ; em3 = ep3 + bdx
  395. END SELECT
  396. sm1x = sm1 ; em1x = em1 ! just copy
  397. sm2x = sm2 ; em2x = em2
  398. sm3x = sm3 ; em3x = em3
  399. sm1y = sm1 ; em1y = em1 ! just copy
  400. sm2y = sm2 ; em2y = em2
  401. sm3y = sm3 ; em3y = em3
  402. ! assigns mostly just to suppress warning messages that INTENT OUT vars not assigned
  403. sp1x = sp1 ; ep1x = ep1 ; sp2x = sp2 ; ep2x = ep2 ; sp3x = sp3 ; ep3x = ep3
  404. sp1y = sp1 ; ep1y = ep1 ; sp2y = sp2 ; ep2y = ep2 ; sp3y = sp3 ; ep3y = ep3
  405. #else
  406. ! This is supplied by the package specific version of module_dm, which
  407. ! is supplied by the external package and copied into the src directory
  408. ! when the code is compiled. The cp command will be found in the externals
  409. ! target of the configure.wrf file for this architecture. Eg: for RSL
  410. ! routine is defined in external/RSL/module_dm.F .
  411. ! Note, it would be very nice to be able to pass parent to this routine;
  412. ! however, there doesn't seem to be a way to do that in F90. That is because
  413. ! to pass a pointer to a domain structure, this call requires an interface
  414. ! definition for wrf_dm_patch_domain (otherwise it will try to convert the
  415. ! pointer to something). In order to provide an interface definition, we
  416. ! would need to either USE module_dm or use an interface block. In either
  417. ! case it generates a circular USE reference, since module_dm uses
  418. ! module_domain. JM 20020416
  419. CALL wrf_dm_patch_domain( id , domdesc , parent_id , parent_domdesc , &
  420. sd1 , ed1 , sp1 , ep1 , sm1 , em1 , &
  421. sd2 , ed2 , sp2 , ep2 , sm2 , em2 , &
  422. sd3 , ed3 , sp3 , ep3 , sm3 , em3 , &
  423. sp1x , ep1x , sm1x , em1x , &
  424. sp2x , ep2x , sm2x , em2x , &
  425. sp3x , ep3x , sm3x , em3x , &
  426. sp1y , ep1y , sm1y , em1y , &
  427. sp2y , ep2y , sm2y , em2y , &
  428. sp3y , ep3y , sm3y , em3y , &
  429. bdx , bdy )
  430. SELECT CASE ( model_data_order )
  431. CASE ( DATA_ORDER_XYZ )
  432. bdy_mask( P_XSB ) = ( sd1 <= sp1 .AND. sp1 <= sd1+spec_bdy_width-1 )
  433. bdy_mask( P_YSB ) = ( sd2 <= sp2 .AND. sp2 <= sd2+spec_bdy_width-1 )
  434. bdy_mask( P_XEB ) = ( ed1-spec_bdy_width-1 <= ep1 .AND. ep1 <= ed1 )
  435. bdy_mask( P_YEB ) = ( ed2-spec_bdy_width-1 <= ep2 .AND. ep2 <= ed2 )
  436. CASE ( DATA_ORDER_YXZ )
  437. bdy_mask( P_XSB ) = ( sd2 <= sp2 .AND. sp2 <= sd2+spec_bdy_width-1 )
  438. bdy_mask( P_YSB ) = ( sd1 <= sp1 .AND. sp1 <= sd1+spec_bdy_width-1 )
  439. bdy_mask( P_XEB ) = ( ed2-spec_bdy_width-1 <= ep2 .AND. ep2 <= ed2 )
  440. bdy_mask( P_YEB ) = ( ed1-spec_bdy_width-1 <= ep1 .AND. ep1 <= ed1 )
  441. CASE ( DATA_ORDER_ZXY )
  442. bdy_mask( P_XSB ) = ( sd2 <= sp2 .AND. sp2 <= sd2+spec_bdy_width-1 )
  443. bdy_mask( P_YSB ) = ( sd3 <= sp3 .AND. sp3 <= sd3+spec_bdy_width-1 )
  444. bdy_mask( P_XEB ) = ( ed2-spec_bdy_width-1 <= ep2 .AND. ep2 <= ed2 )
  445. bdy_mask( P_YEB ) = ( ed3-spec_bdy_width-1 <= ep3 .AND. ep3 <= ed3 )
  446. CASE ( DATA_ORDER_ZYX )
  447. bdy_mask( P_XSB ) = ( sd3 <= sp3 .AND. sp3 <= sd3+spec_bdy_width-1 )
  448. bdy_mask( P_YSB ) = ( sd2 <= sp2 .AND. sp2 <= sd2+spec_bdy_width-1 )
  449. bdy_mask( P_XEB ) = ( ed3-spec_bdy_width-1 <= ep3 .AND. ep3 <= ed3 )
  450. bdy_mask( P_YEB ) = ( ed2-spec_bdy_width-1 <= ep2 .AND. ep2 <= ed2 )
  451. CASE ( DATA_ORDER_XZY )
  452. bdy_mask( P_XSB ) = ( sd1 <= sp1 .AND. sp1 <= sd1+spec_bdy_width-1 )
  453. bdy_mask( P_YSB ) = ( sd3 <= sp3 .AND. sp3 <= sd3+spec_bdy_width-1 )
  454. bdy_mask( P_XEB ) = ( ed1-spec_bdy_width-1 <= ep1 .AND. ep1 <= ed1 )
  455. bdy_mask( P_YEB ) = ( ed3-spec_bdy_width-1 <= ep3 .AND. ep3 <= ed3 )
  456. CASE ( DATA_ORDER_YZX )
  457. bdy_mask( P_XSB ) = ( sd3 <= sp3 .AND. sp3 <= sd3+spec_bdy_width-1 )
  458. bdy_mask( P_YSB ) = ( sd1 <= sp1 .AND. sp1 <= sd1+spec_bdy_width-1 )
  459. bdy_mask( P_XEB ) = ( ed3-spec_bdy_width-1 <= ep3 .AND. ep3 <= ed3 )
  460. bdy_mask( P_YEB ) = ( ed1-spec_bdy_width-1 <= ep1 .AND. ep1 <= ed1 )
  461. END SELECT
  462. #endif
  463. RETURN
  464. END SUBROUTINE wrf_patch_domain
  465. !
  466. SUBROUTINE alloc_and_configure_domain ( domain_id , grid , parent, kid )
  467. !<DESCRIPTION>
  468. ! This subroutine is used to allocate a domain data structure of
  469. ! TYPE(DOMAIN) pointed to by the argument <em>grid</em>, link it into the
  470. ! nested domain hierarchy, and set it's configuration information from
  471. ! the appropriate settings in the WRF namelist file. Specifically, if the
  472. ! domain being allocated and configured is nest, the <em>parent</em>
  473. ! argument will point to the already existing domain data structure for
  474. ! the parent domain and the <em>kid</em> argument will be set to an
  475. ! integer indicating which child of the parent this grid will be (child
  476. ! indices start at 1). If this is the top-level domain, the parent and
  477. ! kid arguments are ignored. <b>WRF domains may have multiple children
  478. ! but only ever have one parent.</b>
  479. !
  480. ! The <em>domain_id</em> argument is the
  481. ! integer handle by which this new domain will be referred; it comes from
  482. ! the grid_id setting in the namelist, and these grid ids correspond to
  483. ! the ordering of settings in the namelist, starting with 1 for the
  484. ! top-level domain. The id of 1 always corresponds to the top-level
  485. ! domain. and these grid ids correspond to the ordering of settings in
  486. ! the namelist, starting with 1 for the top-level domain.
  487. !
  488. ! Model_data_order is provide by USE association of
  489. ! module_driver_constants and is set from dimspec entries in the
  490. ! Registry.
  491. !
  492. ! The allocation of the TYPE(DOMAIN) itself occurs in this routine.
  493. ! However, the numerous multi-dimensional arrays that make up the members
  494. ! of the domain are allocated in the call to alloc_space_field, after
  495. ! wrf_patch_domain has been called to determine the dimensions in memory
  496. ! that should be allocated. It bears noting here that arrays and code
  497. ! that indexes these arrays are always global, regardless of how the
  498. ! model is decomposed over patches. Thus, when arrays are allocated on a
  499. ! given process, the start and end of an array dimension are the global
  500. ! indices of the start and end of that process's subdomain.
  501. !
  502. ! Configuration information for the domain (that is, information from the
  503. ! namelist) is added by the call to <a href=med_add_config_info_to_grid.html>med_add_config_info_to_grid</a>, defined
  504. ! in share/mediation_wrfmain.F.
  505. !</DESCRIPTION>
  506. IMPLICIT NONE
  507. ! Input data.
  508. INTEGER , INTENT(IN) :: domain_id
  509. TYPE( domain ) , POINTER :: grid
  510. TYPE( domain ) , POINTER :: parent
  511. INTEGER , INTENT(IN) :: kid ! which kid of parent am I?
  512. ! Local data.
  513. INTEGER :: sd1 , ed1 , sp1 , ep1 , sm1 , em1
  514. INTEGER :: sd2 , ed2 , sp2 , ep2 , sm2 , em2
  515. INTEGER :: sd3 , ed3 , sp3 , ep3 , sm3 , em3
  516. INTEGER :: sd1x , ed1x , sp1x , ep1x , sm1x , em1x
  517. INTEGER :: sd2x , ed2x , sp2x , ep2x , sm2x , em2x
  518. INTEGER :: sd3x , ed3x , sp3x , ep3x , sm3x , em3x
  519. INTEGER :: sd1y , ed1y , sp1y , ep1y , sm1y , em1y
  520. INTEGER :: sd2y , ed2y , sp2y , ep2y , sm2y , em2y
  521. INTEGER :: sd3y , ed3y , sp3y , ep3y , sm3y , em3y
  522. TYPE(domain) , POINTER :: new_grid
  523. INTEGER :: i
  524. INTEGER :: parent_id , parent_domdesc , new_domdesc
  525. INTEGER :: bdyzone_x , bdyzone_y
  526. INTEGER :: nx, ny
  527. ! This next step uses information that is listed in the registry as namelist_derived
  528. ! to properly size the domain and the patches; this in turn is stored in the new_grid
  529. ! data structure
  530. data_ordering : SELECT CASE ( model_data_order )
  531. CASE ( DATA_ORDER_XYZ )
  532. CALL nl_get_s_we( domain_id , sd1 )
  533. CALL nl_get_e_we( domain_id , ed1 )
  534. CALL nl_get_s_sn( domain_id , sd2 )
  535. CALL nl_get_e_sn( domain_id , ed2 )
  536. CALL nl_get_s_vert( domain_id , sd3 )
  537. CALL nl_get_e_vert( domain_id , ed3 )
  538. nx = ed1-sd1+1
  539. ny = ed2-sd2+1
  540. CASE ( DATA_ORDER_YXZ )
  541. CALL nl_get_s_sn( domain_id , sd1 )
  542. CALL nl_get_e_sn( domain_id , ed1 )
  543. CALL nl_get_s_we( domain_id , sd2 )
  544. CALL nl_get_e_we( domain_id , ed2 )
  545. CALL nl_get_s_vert( domain_id , sd3 )
  546. CALL nl_get_e_vert( domain_id , ed3 )
  547. nx = ed2-sd2+1
  548. ny = ed1-sd1+1
  549. CASE ( DATA_ORDER_ZXY )
  550. CALL nl_get_s_vert( domain_id , sd1 )
  551. CALL nl_get_e_vert( domain_id , ed1 )
  552. CALL nl_get_s_we( domain_id , sd2 )
  553. CALL nl_get_e_we( domain_id , ed2 )
  554. CALL nl_get_s_sn( domain_id , sd3 )
  555. CALL nl_get_e_sn( domain_id , ed3 )
  556. nx = ed2-sd2+1
  557. ny = ed3-sd3+1
  558. CASE ( DATA_ORDER_ZYX )
  559. CALL nl_get_s_vert( domain_id , sd1 )
  560. CALL nl_get_e_vert( domain_id , ed1 )
  561. CALL nl_get_s_sn( domain_id , sd2 )
  562. CALL nl_get_e_sn( domain_id , ed2 )
  563. CALL nl_get_s_we( domain_id , sd3 )
  564. CALL nl_get_e_we( domain_id , ed3 )
  565. nx = ed3-sd3+1
  566. ny = ed2-sd2+1
  567. CASE ( DATA_ORDER_XZY )
  568. CALL nl_get_s_we( domain_id , sd1 )
  569. CALL nl_get_e_we( domain_id , ed1 )
  570. CALL nl_get_s_vert( domain_id , sd2 )
  571. CALL nl_get_e_vert( domain_id , ed2 )
  572. CALL nl_get_s_sn( domain_id , sd3 )
  573. CALL nl_get_e_sn( domain_id , ed3 )
  574. nx = ed1-sd1+1
  575. ny = ed3-sd3+1
  576. CASE ( DATA_ORDER_YZX )
  577. CALL nl_get_s_sn( domain_id , sd1 )
  578. CALL nl_get_e_sn( domain_id , ed1 )
  579. CALL nl_get_s_vert( domain_id , sd2 )
  580. CALL nl_get_e_vert( domain_id , ed2 )
  581. CALL nl_get_s_we( domain_id , sd3 )
  582. CALL nl_get_e_we( domain_id , ed3 )
  583. nx = ed3-sd3+1
  584. ny = ed1-sd1+1
  585. END SELECT data_ordering
  586. IF ( num_time_levels > 3 ) THEN
  587. WRITE ( wrf_err_message , * ) 'alloc_and_configure_domain: ', &
  588. 'Incorrect value for num_time_levels ', num_time_levels
  589. CALL wrf_error_fatal ( TRIM ( wrf_err_message ) )
  590. ENDIF
  591. IF (ASSOCIATED(parent)) THEN
  592. parent_id = parent%id
  593. parent_domdesc = parent%domdesc
  594. ELSE
  595. parent_id = -1
  596. parent_domdesc = -1
  597. ENDIF
  598. ! provided by application, WRF defines in share/module_bc.F
  599. CALL get_bdyzone_x( bdyzone_x )
  600. CALL get_bdyzone_y( bdyzone_y )
  601. ALLOCATE ( new_grid )
  602. ALLOCATE( new_grid%head_statevars )
  603. NULLIFY( new_grid%head_statevars%next)
  604. new_grid%tail_statevars => new_grid%head_statevars
  605. ALLOCATE ( new_grid%parents( max_parents ) )
  606. ALLOCATE ( new_grid%nests( max_nests ) )
  607. NULLIFY( new_grid%sibling )
  608. DO i = 1, max_nests
  609. NULLIFY( new_grid%nests(i)%ptr )
  610. ENDDO
  611. NULLIFY (new_grid%next)
  612. NULLIFY (new_grid%same_level)
  613. NULLIFY (new_grid%i_start)
  614. NULLIFY (new_grid%j_start)
  615. NULLIFY (new_grid%i_end)
  616. NULLIFY (new_grid%j_end)
  617. ALLOCATE( new_grid%domain_clock )
  618. new_grid%domain_clock_created = .FALSE.
  619. ALLOCATE( new_grid%alarms( MAX_WRF_ALARMS ) ) ! initialize in setup_timekeeping
  620. ALLOCATE( new_grid%alarms_created( MAX_WRF_ALARMS ) )
  621. DO i = 1, MAX_WRF_ALARMS
  622. new_grid%alarms_created( i ) = .FALSE.
  623. ENDDO
  624. new_grid%time_set = .FALSE.
  625. new_grid%is_intermediate = .FALSE.
  626. new_grid%have_displayed_alloc_stats = .FALSE.
  627. ! set up the pointers that represent the nest hierarchy
  628. ! set this up *prior* to calling the patching or allocation
  629. ! routines so that implementations of these routines can
  630. ! traverse the nest hierarchy (through the root head_grid)
  631. ! if they need to
  632. IF ( domain_id .NE. 1 ) THEN
  633. new_grid%parents(1)%ptr => parent
  634. new_grid%num_parents = 1
  635. parent%nests(kid)%ptr => new_grid
  636. new_grid%child_of_parent(1) = kid ! note assumption that nest can have only 1 parent
  637. parent%num_nests = parent%num_nests + 1
  638. END IF
  639. new_grid%id = domain_id ! this needs to be assigned prior to calling wrf_patch_domain
  640. CALL wrf_patch_domain( domain_id , new_domdesc , parent, parent_id, parent_domdesc , &
  641. sd1 , ed1 , sp1 , ep1 , sm1 , em1 , & ! z-xpose dims
  642. sd2 , ed2 , sp2 , ep2 , sm2 , em2 , & ! (standard)
  643. sd3 , ed3 , sp3 , ep3 , sm3 , em3 , &
  644. sp1x , ep1x , sm1x , em1x , & ! x-xpose dims
  645. sp2x , ep2x , sm2x , em2x , &
  646. sp3x , ep3x , sm3x , em3x , &
  647. sp1y , ep1y , sm1y , em1y , & ! y-xpose dims
  648. sp2y , ep2y , sm2y , em2y , &
  649. sp3y , ep3y , sm3y , em3y , &
  650. bdyzone_x , bdyzone_y , new_grid%bdy_mask &
  651. )
  652. new_grid%domdesc = new_domdesc
  653. new_grid%num_nests = 0
  654. new_grid%num_siblings = 0
  655. new_grid%num_parents = 0
  656. new_grid%max_tiles = 0
  657. new_grid%num_tiles_spec = 0
  658. new_grid%nframes = 0 ! initialize the number of frames per file (array assignment)
  659. #if (EM_CORE == 1)
  660. new_grid%stepping_to_time = .FALSE.
  661. new_grid%adaptation_domain = 1
  662. new_grid%last_step_updated = -1
  663. #endif
  664. CALL alloc_space_field ( new_grid, domain_id , 3 , 3 , .FALSE. , &
  665. sd1, ed1, sd2, ed2, sd3, ed3, &
  666. sm1, em1, sm2, em2, sm3, em3, &
  667. sp1, ep1, sp2, ep2, sp3, ep3, &
  668. sp1x, ep1x, sp2x, ep2x, sp3x, ep3x, &
  669. sp1y, ep1y, sp2y, ep2y, sp3y, ep3y, &
  670. sm1x, em1x, sm2x, em2x, sm3x, em3x, & ! x-xpose
  671. sm1y, em1y, sm2y, em2y, sm3y, em3y & ! y-xpose
  672. )
  673. #if MOVE_NESTS
  674. !set these here, after alloc_space_field, which initializes vc_i, vc_j to zero
  675. new_grid%xi = -1.0
  676. new_grid%xj = -1.0
  677. new_grid%vc_i = -1.0
  678. new_grid%vc_j = -1.0
  679. #endif
  680. new_grid%sd31 = sd1
  681. new_grid%ed31 = ed1
  682. new_grid%sp31 = sp1
  683. new_grid%ep31 = ep1
  684. new_grid%sm31 = sm1
  685. new_grid%em31 = em1
  686. new_grid%sd32 = sd2
  687. new_grid%ed32 = ed2
  688. new_grid%sp32 = sp2
  689. new_grid%ep32 = ep2
  690. new_grid%sm32 = sm2
  691. new_grid%em32 = em2
  692. new_grid%sd33 = sd3
  693. new_grid%ed33 = ed3
  694. new_grid%sp33 = sp3
  695. new_grid%ep33 = ep3
  696. new_grid%sm33 = sm3
  697. new_grid%em33 = em3
  698. new_grid%sp31x = sp1x
  699. new_grid%ep31x = ep1x
  700. new_grid%sm31x = sm1x
  701. new_grid%em31x = em1x
  702. new_grid%sp32x = sp2x
  703. new_grid%ep32x = ep2x
  704. new_grid%sm32x = sm2x
  705. new_grid%em32x = em2x
  706. new_grid%sp33x = sp3x
  707. new_grid%ep33x = ep3x
  708. new_grid%sm33x = sm3x
  709. new_grid%em33x = em3x
  710. new_grid%sp31y = sp1y
  711. new_grid%ep31y = ep1y
  712. new_grid%sm31y = sm1y
  713. new_grid%em31y = em1y
  714. new_grid%sp32y = sp2y
  715. new_grid%ep32y = ep2y
  716. new_grid%sm32y = sm2y
  717. new_grid%em32y = em2y
  718. new_grid%sp33y = sp3y
  719. new_grid%ep33y = ep3y
  720. new_grid%sm33y = sm3y
  721. new_grid%em33y = em3y
  722. SELECT CASE ( model_data_order )
  723. CASE ( DATA_ORDER_XYZ )
  724. new_grid%sd21 = sd1 ; new_grid%sd22 = sd2 ;
  725. new_grid%ed21 = ed1 ; new_grid%ed22 = ed2 ;
  726. new_grid%sp21 = sp1 ; new_grid%sp22 = sp2 ;
  727. new_grid%ep21 = ep1 ; new_grid%ep22 = ep2 ;
  728. new_grid%sm21 = sm1 ; new_grid%sm22 = sm2 ;
  729. new_grid%em21 = em1 ; new_grid%em22 = em2 ;
  730. new_grid%sd11 = sd1
  731. new_grid%ed11 = ed1
  732. new_grid%sp11 = sp1
  733. new_grid%ep11 = ep1
  734. new_grid%sm11 = sm1
  735. new_grid%em11 = em1
  736. CASE ( DATA_ORDER_YXZ )
  737. new_grid%sd21 = sd1 ; new_grid%sd22 = sd2 ;
  738. new_grid%ed21 = ed1 ; new_grid%ed22 = ed2 ;
  739. new_grid%sp21 = sp1 ; new_grid%sp22 = sp2 ;
  740. new_grid%ep21 = ep1 ; new_grid%ep22 = ep2 ;
  741. new_grid%sm21 = sm1 ; new_grid%sm22 = sm2 ;
  742. new_grid%em21 = em1 ; new_grid%em22 = em2 ;
  743. new_grid%sd11 = sd1
  744. new_grid%ed11 = ed1
  745. new_grid%sp11 = sp1
  746. new_grid%ep11 = ep1
  747. new_grid%sm11 = sm1
  748. new_grid%em11 = em1
  749. CASE ( DATA_ORDER_ZXY )
  750. new_grid%sd21 = sd2 ; new_grid%sd22 = sd3 ;
  751. new_grid%ed21 = ed2 ; new_grid%ed22 = ed3 ;
  752. new_grid%sp21 = sp2 ; new_grid%sp22 = sp3 ;
  753. new_grid%ep21 = ep2 ; new_grid%ep22 = ep3 ;
  754. new_grid%sm21 = sm2 ; new_grid%sm22 = sm3 ;
  755. new_grid%em21 = em2 ; new_grid%em22 = em3 ;
  756. new_grid%sd11 = sd2
  757. new_grid%ed11 = ed2
  758. new_grid%sp11 = sp2
  759. new_grid%ep11 = ep2
  760. new_grid%sm11 = sm2
  761. new_grid%em11 = em2
  762. CASE ( DATA_ORDER_ZYX )
  763. new_grid%sd21 = sd2 ; new_grid%sd22 = sd3 ;
  764. new_grid%ed21 = ed2 ; new_grid%ed22 = ed3 ;
  765. new_grid%sp21 = sp2 ; new_grid%sp22 = sp3 ;
  766. new_grid%ep21 = ep2 ; new_grid%ep22 = ep3 ;
  767. new_grid%sm21 = sm2 ; new_grid%sm22 = sm3 ;
  768. new_grid%em21 = em2 ; new_grid%em22 = em3 ;
  769. new_grid%sd11 = sd2
  770. new_grid%ed11 = ed2
  771. new_grid%sp11 = sp2
  772. new_grid%ep11 = ep2
  773. new_grid%sm11 = sm2
  774. new_grid%em11 = em2
  775. CASE ( DATA_ORDER_XZY )
  776. new_grid%sd21 = sd1 ; new_grid%sd22 = sd3 ;
  777. new_grid%ed21 = ed1 ; new_grid%ed22 = ed3 ;
  778. new_grid%sp21 = sp1 ; new_grid%sp22 = sp3 ;
  779. new_grid%ep21 = ep1 ; new_grid%ep22 = ep3 ;
  780. new_grid%sm21 = sm1 ; new_grid%sm22 = sm3 ;
  781. new_grid%em21 = em1 ; new_grid%em22 = em3 ;
  782. new_grid%sd11 = sd1
  783. new_grid%ed11 = ed1
  784. new_grid%sp11 = sp1
  785. new_grid%ep11 = ep1
  786. new_grid%sm11 = sm1
  787. new_grid%em11 = em1
  788. CASE ( DATA_ORDER_YZX )
  789. new_grid%sd21 = sd1 ; new_grid%sd22 = sd3 ;
  790. new_grid%ed21 = ed1 ; new_grid%ed22 = ed3 ;
  791. new_grid%sp21 = sp1 ; new_grid%sp22 = sp3 ;
  792. new_grid%ep21 = ep1 ; new_grid%ep22 = ep3 ;
  793. new_grid%sm21 = sm1 ; new_grid%sm22 = sm3 ;
  794. new_grid%em21 = em1 ; new_grid%em22 = em3 ;
  795. new_grid%sd11 = sd1
  796. new_grid%ed11 = ed1
  797. new_grid%sp11 = sp1
  798. new_grid%ep11 = ep1
  799. new_grid%sm11 = sm1
  800. new_grid%em11 = em1
  801. END SELECT
  802. CALL med_add_config_info_to_grid ( new_grid ) ! this is a mediation layer routine
  803. ! Some miscellaneous state that is in the Registry but not namelist data
  804. new_grid%tiled = .false.
  805. new_grid%patched = .false.
  806. NULLIFY(new_grid%mapping)
  807. ! This next set of includes causes all but the namelist_derived variables to be
  808. ! properly assigned to the new_grid record
  809. grid => new_grid
  810. ! Allocate storage for time series metadata
  811. ALLOCATE( grid%lattsloc( grid%max_ts_locs ) )
  812. ALLOCATE( grid%lontsloc( grid%max_ts_locs ) )
  813. ALLOCATE( grid%nametsloc( grid%max_ts_locs ) )
  814. ALLOCATE( grid%desctsloc( grid%max_ts_locs ) )
  815. ALLOCATE( grid%itsloc( grid%max_ts_locs ) )
  816. ALLOCATE( grid%jtsloc( grid%max_ts_locs ) )
  817. ALLOCATE( grid%id_tsloc( grid%max_ts_locs ) )
  818. ALLOCATE( grid%ts_filename( grid%max_ts_locs ) )
  819. grid%ntsloc = 0
  820. grid%ntsloc_domain = 0
  821. #if (EM_CORE == 1)
  822. ! Allocate storage for track metadata
  823. ALLOCATE( grid%track_time_in( grid%track_loc_in ) )
  824. ALLOCATE( grid%track_lat_in( grid%track_loc_in ) )
  825. ALLOCATE( grid%track_lon_in( grid%track_loc_in ) )
  826. ALLOCATE( grid%track_time_domain( grid%track_loc_in ) )
  827. ALLOCATE( grid%track_lat_domain( grid%track_loc_in ) )
  828. ALLOCATE( grid%track_lon_domain( grid%track_loc_in ) )
  829. ALLOCATE( grid%track_i( grid%track_loc_in ) )
  830. ALLOCATE( grid%track_j( grid%track_loc_in ) )
  831. grid%track_loc = 0
  832. grid%track_loc_domain = 0
  833. grid%track_have_calculated = .FALSE.
  834. grid%track_have_input = .FALSE.
  835. #endif
  836. #ifdef DM_PARALLEL
  837. CALL wrf_get_dm_communicator ( grid%communicator )
  838. CALL wrf_dm_define_comms( grid )
  839. #endif
  840. END SUBROUTINE alloc_and_configure_domain
  841. SUBROUTINE get_fieldstr(ix,c,instr,outstr,noutstr,noerr)
  842. IMPLICIT NONE
  843. INTEGER, INTENT(IN) :: ix
  844. CHARACTER*(*), INTENT(IN) :: c
  845. CHARACTER*(*), INTENT(IN) :: instr
  846. CHARACTER*(*), INTENT(OUT) :: outstr
  847. INTEGER, INTENT(IN) :: noutstr ! length of outstr
  848. LOGICAL, INTENT(INOUT) :: noerr ! status
  849. !local
  850. INTEGER, PARAMETER :: MAX_DEXES = 100
  851. INTEGER I, PREV, IDEX
  852. INTEGER DEXES(MAX_DEXES)
  853. outstr = ""
  854. prev = 1
  855. dexes(1) = 1
  856. DO i = 2,MAX_DEXES
  857. idex = INDEX(instr(prev:LEN(TRIM(instr))),c)
  858. IF ( idex .GT. 0 ) THEN
  859. dexes(i) = idex+prev
  860. prev = dexes(i)+1
  861. ELSE
  862. dexes(i) = LEN(TRIM(instr))+2
  863. ENDIF
  864. ENDDO
  865. IF ( (dexes(ix+1)-2)-(dexes(ix)) .GT. noutstr ) THEN
  866. noerr = .FALSE. ! would overwrite
  867. ELSE IF( dexes(ix) .EQ. dexes(ix+1) ) THEN
  868. noerr = .FALSE. ! not found
  869. ELSE
  870. outstr = instr(dexes(ix):(dexes(ix+1)-2))
  871. noerr = noerr .AND. .TRUE.
  872. ENDIF
  873. END SUBROUTINE get_fieldstr
  874. SUBROUTINE change_to_lower_case(instr,outstr)
  875. CHARACTER*(*) ,INTENT(IN) :: instr
  876. CHARACTER*(*) ,INTENT(OUT) :: outstr
  877. !Local
  878. CHARACTER*1 :: c
  879. INTEGER ,PARAMETER :: upper_to_lower =IACHAR('a')-IACHAR('A')
  880. INTEGER :: i,n,n1
  881. !
  882. outstr = ' '
  883. N = len(instr)
  884. N1 = len(outstr)
  885. N = MIN(N,N1)
  886. outstr(1:N) = instr(1:N)
  887. DO i=1,N
  888. c = instr(i:i)
  889. if('A'<=c .and. c <='Z') outstr(i:i)=achar(iachar(c)+upper_to_lower)
  890. ENDDO
  891. RETURN
  892. END SUBROUTINE change_to_lower_case
  893. !
  894. SUBROUTINE modify_io_masks1 ( grid , id )
  895. IMPLICIT NONE
  896. #include "streams.h"
  897. INTEGER , INTENT(IN ) :: id
  898. TYPE(domain), POINTER :: grid
  899. ! Local
  900. TYPE(fieldlist), POINTER :: p, q
  901. INTEGER, PARAMETER :: read_unit = 10
  902. LOGICAL, EXTERNAL :: wrf_dm_on_monitor
  903. CHARACTER*256 :: fname, inln, mess, dname, t1, lookee
  904. CHARACTER*256 :: fieldlst
  905. CHARACTER*1 :: op, strmtyp
  906. CHARACTER*3 :: strmid
  907. CHARACTER*10 :: strmtyp_name
  908. INTEGER :: io_status
  909. INTEGER :: strmtyp_int, count_em
  910. INTEGER :: lineno, fieldno, istrm, retval, itrace
  911. LOGICAL :: keepgoing, noerr, gavewarning, ignorewarning, found
  912. LOGICAL, SAVE :: you_warned_me = .FALSE.
  913. LOGICAL, SAVE :: you_warned_me2(max_hst_mods,max_domains) = .FALSE.
  914. gavewarning = .FALSE.
  915. CALL nl_get_iofields_filename( id, fname )
  916. IF ( grid%is_intermediate ) RETURN ! short circuit
  917. IF ( TRIM(fname) .EQ. "NONE_SPECIFIED" ) RETURN ! short circuit
  918. IF ( wrf_dm_on_monitor() ) THEN
  919. OPEN ( UNIT = read_unit , &
  920. FILE = TRIM(fname) , &
  921. FORM = "FORMATTED" , &
  922. STATUS = "OLD" , &
  923. IOSTAT = io_status )
  924. IF ( io_status .EQ. 0 ) THEN ! only on success
  925. keepgoing = .TRUE.
  926. lineno = 0
  927. count_em = 0 ! Count the total number of fields
  928. DO WHILE ( keepgoing )
  929. READ(UNIT=read_unit,FMT='(A)',IOSTAT=io_status) inln
  930. keepgoing = (io_status .EQ. 0) .AND. (LEN(TRIM(inln)) .GT. 0)
  931. IF ( keepgoing ) THEN
  932. lineno = lineno + 1
  933. IF ( .NOT. LEN(TRIM(inln)) .LT. LEN(inln) ) THEN
  934. WRITE(mess,*)'W A R N I N G : Line ',lineno,' of ',TRIM(fname),' is too long. Limit is ',LEN(inln),' characters.'
  935. gavewarning = .TRUE.
  936. ENDIF
  937. IF ( INDEX(inln,'#') .EQ. 0 ) THEN ! skip comments, which is a # anywhere on line
  938. IF ( keepgoing ) THEN
  939. noerr = .TRUE.
  940. CALL get_fieldstr(1,':',inln,op,1,noerr) ! + is add, - is remove
  941. IF ( TRIM(op) .NE. '+' .AND. TRIM(op) .NE. '-' ) THEN
  942. WRITE(mess,*)'W A R N I N G : unknown operation ',TRIM(op),' (should be + or -). Line ',lineno
  943. gavewarning = .TRUE.
  944. ENDIF
  945. CALL get_fieldstr(2,':',inln,t1,1,noerr) ! i is input, h is history
  946. CALL change_to_lower_case(t1,strmtyp)
  947. SELECT CASE (TRIM(strmtyp))
  948. CASE ('h')
  949. strmtyp_name = 'history'
  950. strmtyp_int = first_history
  951. CASE ('i')
  952. strmtyp_name = 'input'
  953. strmtyp_int = first_input
  954. CASE DEFAULT
  955. WRITE(mess,*)'W A R N I N G : unknown stream type ',TRIM(strmtyp),'. Line ',lineno
  956. gavewarning = .TRUE.
  957. END SELECT
  958. CALL get_fieldstr(3,':',inln,strmid,3,noerr) ! number of stream (main input and hist are 0)
  959. READ(strmid,'(I3)') istrm
  960. IF ( istrm .LT. 0 .OR. istrm .GT. last_history ) THEN
  961. WRITE(mess,*)'W A R N I N G : invalid stream id ',istrm,' (should be 0 <= id <= ',last_history,'). Line ',lineno
  962. gavewarning = .TRUE.
  963. ENDIF
  964. CALL get_fieldstr(4,':',inln,fieldlst,1024,noerr) ! get list of fields
  965. IF ( noerr ) THEN
  966. fieldno = 1
  967. CALL get_fieldstr(fieldno,',',fieldlst,t1,256,noerr)
  968. CALL change_to_lower_case(t1,lookee)
  969. DO WHILE ( noerr ) ! linear search, blargh...
  970. p => grid%head_statevars
  971. found = .FALSE.
  972. count_em = count_em + 1
  973. DO WHILE ( ASSOCIATED( p ) )
  974. IF ( p%Ndim .EQ. 4 .AND. p%scalar_array ) THEN
  975. DO itrace = PARAM_FIRST_SCALAR , p%num_table(grid%id)
  976. CALL change_to_lower_case( p%dname_table( grid%id, itrace ) , dname )
  977. IF ( TRIM(dname) .EQ. TRIM(lookee) ) &
  978. CALL warn_me_or_set_mask (id, istrm, lineno, strmtyp_int, count_em, op, &
  979. strmtyp_name, dname, fname, lookee, &
  980. p%streams_table(grid%id,itrace)%stream, &
  981. mess, found, you_warned_me2)
  982. ENDDO
  983. ELSE
  984. IF ( p%Ntl .GT. 0 ) THEN
  985. CALL change_to_lower_case(p%DataName(1:LEN(TRIM(p%DataName))-2),dname)
  986. ELSE
  987. CALL change_to_lower_case(p%DataName,dname)
  988. ENDIF
  989. IF ( TRIM(dname) .EQ. TRIM(lookee) ) &
  990. CALL warn_me_or_set_mask (id, istrm, lineno, strmtyp_int, count_em, op, &
  991. strmtyp_name, dname, fname, lookee, &
  992. p%streams, mess, found, you_warned_me2)
  993. ENDIF
  994. p => p%next
  995. ENDDO
  996. IF ( .NOT. found ) THEN
  997. WRITE(mess,*)'W A R N I N G : Unable to modify mask for ',TRIM(lookee),&
  998. '. Variable not found. File: ',TRIM(fname),' at line ',lineno
  999. CALL wrf_message(mess)
  1000. gavewarning = .TRUE.
  1001. ENDIF
  1002. fieldno = fieldno + 1
  1003. CALL get_fieldstr(fieldno,',',fieldlst,t1,256,noerr)
  1004. CALL change_to_lower_case(t1,lookee)
  1005. ENDDO
  1006. ELSE
  1007. WRITE(mess,*)'W A R N I N G : Problem reading ',TRIM(fname),' at line ',lineno
  1008. CALL wrf_message(mess)
  1009. gavewarning = .TRUE.
  1010. ENDIF
  1011. ENDIF ! keepgoing
  1012. ENDIF ! skip comments
  1013. ENDIF ! keepgoing
  1014. ENDDO
  1015. ELSE
  1016. WRITE(mess,*)'W A R N I N G : Problem opening ',TRIM(fname)
  1017. CALL wrf_message(mess)
  1018. gavewarning = .TRUE.
  1019. ENDIF
  1020. CLOSE( read_unit )
  1021. IF ( gavewarning ) THEN
  1022. CALL nl_get_ignore_iofields_warning(1,ignorewarning)
  1023. IF ( .NOT. ignorewarning ) THEN
  1024. CALL wrf_message(mess)
  1025. WRITE(mess,*)'modify_io_masks: problems reading ',TRIM(fname)
  1026. CALL wrf_message(mess)
  1027. CALL wrf_error_fatal('Set ignore_iofields_warn to true in namelist to ignore')
  1028. ELSE
  1029. IF ( .NOT. you_warned_me ) THEN
  1030. if ( .NOT. you_warned_me2(count_em,id) ) CALL wrf_message(mess) ! Don't repeat the W A R N I N G message
  1031. WRITE(mess,*)'Ignoring problems reading ',TRIM(fname)
  1032. CALL wrf_message(mess)
  1033. CALL wrf_message('Continuing. To make this a fatal error, set ignore_iofields_warn to false in namelist' )
  1034. CALL wrf_message(' ')
  1035. you_warned_me = .TRUE.
  1036. ENDIF
  1037. ENDIF
  1038. ENDIF
  1039. ENDIF ! wrf_dm_on_monitor
  1040. #ifdef DM_PARALLEL
  1041. ! broadcast the new masks to the other tasks
  1042. p => grid%head_statevars
  1043. DO WHILE ( ASSOCIATED( p ) )
  1044. IF ( p%Ndim .EQ. 4 .AND. p%scalar_array ) THEN
  1045. DO itrace = PARAM_FIRST_SCALAR , p%num_table(grid%id)
  1046. CALL wrf_dm_bcast_integer( p%streams_table(grid%id,itrace)%stream, IO_MASK_SIZE )
  1047. ENDDO
  1048. ELSE
  1049. CALL wrf_dm_bcast_integer( p%streams, IO_MASK_SIZE )
  1050. ENDIF
  1051. p => p%next
  1052. ENDDO
  1053. #endif
  1054. END SUBROUTINE modify_io_masks1
  1055. SUBROUTINE warn_me_or_set_mask (id, istrm, lineno, strmtyp_int, count_em, op, &
  1056. strmtyp_name, dname, fname, lookee, &
  1057. p_stream, mess, found, you_warned_me2)
  1058. IMPLICIT NONE
  1059. ! See if a field that is requested to be added to or removed from the I/O stream
  1060. ! is already present or absent
  1061. ! If the requested action has already been done, write a warning message
  1062. ! If not, satisfy the request
  1063. INTEGER, INTENT(IN ) :: id, istrm, lineno, strmtyp_int
  1064. INTEGER, INTENT(IN ) :: p_stream(*), count_em
  1065. CHARACTER*1, INTENT(IN ) :: op
  1066. CHARACTER*10, INTENT(IN ) :: strmtyp_name
  1067. CHARACTER*256, INTENT(IN ) :: dname, fname, lookee
  1068. CHARACTER*256, INTENT(OUT) :: mess
  1069. LOGICAL, INTENT(OUT) :: found
  1070. LOGICAL, INTENT(INOUT) :: you_warned_me2(max_hst_mods,max_domains)
  1071. ! Local
  1072. INTEGER :: retval
  1073. found = .TRUE.
  1074. IF ( TRIM(op) .EQ. '+' ) THEN
  1075. CALL get_mask( p_stream, strmtyp_int + istrm - 1, retval )
  1076. IF ( retval .NE. 0 ) THEN
  1077. WRITE(mess,*) 'Domain ',id, ' W A R N I N G : Variable ',TRIM(lookee),' already on ', &
  1078. TRIM(strmtyp_name), ' stream ',istrm, '. File: ', TRIM(fname),' at line ',lineno
  1079. ELSE
  1080. WRITE(mess,*) 'Domain ', id, ' Setting ', TRIM(strmtyp_name), ' stream ',istrm,' for ', &
  1081. TRIM(DNAME) ; CALL wrf_debug(1,mess)
  1082. CALL set_mask( p_stream, strmtyp_int + istrm - 1 )
  1083. ENDIF
  1084. ELSE IF ( TRIM(op) .EQ. '-' ) THEN
  1085. CALL get_mask( p_stream, strmtyp_int + istrm - 1, retval )
  1086. IF ( retval .EQ. 0 ) THEN
  1087. WRITE(mess,*) 'Domain ',id, ' W A R N I N G : Variable ',TRIM(lookee),' already off ', &
  1088. TRIM(strmtyp_name), ' stream ',istrm, '. File: ',TRIM(fname),' at line ',lineno
  1089. ELSE
  1090. WRITE(mess,*) 'Domain ', id, ' Resetting ', TRIM(strmtyp_name), ' stream ',istrm,' for ', &
  1091. TRIM(DNAME) ; CALL wrf_debug(1,mess)
  1092. CALL reset_mask( p_stream, strmtyp_int + istrm - 1)
  1093. ENDIF
  1094. ENDIF
  1095. IF ( count_em > max_hst_mods ) THEN
  1096. WRITE(mess,*)'ERROR module_domain: Array size for you_warned_me2 is fixed at ',max_hst_mods
  1097. CALL wrf_message(mess)
  1098. CALL wrf_error_fatal('Did you really type > max_hst_mods fields into ', TRIM(fname) ,' ?')
  1099. ELSE
  1100. IF ( .NOT. you_warned_me2(count_em,id) ) THEN
  1101. CALL wrf_message(mess) ! Write warning message once for each field
  1102. you_warned_me2(count_em,id) = .TRUE.
  1103. ENDIF
  1104. ENDIF
  1105. END SUBROUTINE warn_me_or_set_mask
  1106. ! This routine ALLOCATEs the required space for the meteorological fields
  1107. ! for a specific domain. The fields are simply ALLOCATEd as an -1. They
  1108. ! are referenced as wind, temperature, moisture, etc. in routines that are
  1109. ! below this top-level of data allocation and management (in the solve routine
  1110. ! and below).
  1111. SUBROUTINE alloc_space_field ( grid, id, setinitval_in , tl_in , inter_domain_in , &
  1112. sd31, ed31, sd32, ed32, sd33, ed33, &
  1113. sm31 , em31 , sm32 , em32 , sm33 , em33 , &
  1114. sp31 , ep31 , sp32 , ep32 , sp33 , ep33 , &
  1115. sp31x, ep31x, sp32x, ep32x, sp33x, ep33x, &
  1116. sp31y, ep31y, sp32y, ep32y, sp33y, ep33y, &
  1117. sm31x, em31x, sm32x, em32x, sm33x, em33x, &
  1118. sm31y, em31y, sm32y, em32y, sm33y, em33y )
  1119. USE module_alloc_space_0, ONLY : alloc_space_field_core_0
  1120. USE module_alloc_space_1, ONLY : alloc_space_field_core_1
  1121. USE module_alloc_space_2, ONLY : alloc_space_field_core_2
  1122. USE module_alloc_space_3, ONLY : alloc_space_field_core_3
  1123. USE module_alloc_space_4, ONLY : alloc_space_field_core_4
  1124. USE module_alloc_space_5, ONLY : alloc_space_field_core_5
  1125. USE module_alloc_space_6, ONLY : alloc_space_field_core_6
  1126. USE module_alloc_space_7, ONLY : alloc_space_field_core_7
  1127. USE module_alloc_space_8, ONLY : alloc_space_field_core_8
  1128. USE module_alloc_space_9, ONLY : alloc_space_field_core_9
  1129. IMPLICIT NONE
  1130. ! Input data.
  1131. TYPE(domain) , POINTER :: grid
  1132. INTEGER , INTENT(IN) :: id
  1133. INTEGER , INTENT(IN) :: setinitval_in ! 3 = everything, 1 = arrays only, 0 = none
  1134. INTEGER , INTENT(IN) :: sd31, ed31, sd32, ed32, sd33, ed33
  1135. INTEGER , INTENT(IN) :: sm31, em31, sm32, em32, sm33, em33
  1136. INTEGER , INTENT(IN) :: sp31, ep31, sp32, ep32, sp33, ep33
  1137. INTEGER , INTENT(IN) :: sp31x, ep31x, sp32x, ep32x, sp33x, ep33x
  1138. INTEGER , INTENT(IN) :: sp31y, ep31y, sp32y, ep32y, sp33y, ep33y
  1139. INTEGER , INTENT(IN) :: sm31x, em31x, sm32x, em32x, sm33x, em33x
  1140. INTEGER , INTENT(IN) :: sm31y, em31y, sm32y, em32y, sm33y, em33y
  1141. ! this argument is a bitmask. First bit is time level 1, second is time level 2, and so on.
  1142. ! e.g. to set both 1st and second time level, use 3
  1143. ! to set only 1st use 1
  1144. ! to set only 2st use 2
  1145. INTEGER , INTENT(IN) :: tl_in
  1146. ! true if the allocation is for an intermediate domain (for nesting); only certain fields allocated
  1147. ! false otherwise (all allocated, modulo tl above)
  1148. LOGICAL , INTENT(IN) :: inter_domain_in
  1149. ! Local
  1150. INTEGER(KIND=8) num_bytes_allocated
  1151. INTEGER idum1, idum2
  1152. #if (EM_CORE == 1)
  1153. IF ( grid%id .EQ. 1 ) CALL wrf_message ( &
  1154. 'DYNAMICS OPTION: Eulerian Mass Coordinate ')
  1155. #endif
  1156. #if (NMM_CORE == 1)
  1157. IF ( grid%id .EQ. 1 ) &
  1158. CALL wrf_message ( 'DYNAMICS OPTION: nmm dyncore' )
  1159. #endif
  1160. #if (COAMPS_CORE == 1)
  1161. IF ( grid%id .EQ. 1 ) &
  1162. CALL wrf_message ( 'DYNAMICS OPTION: coamps dyncore' )
  1163. #endif
  1164. CALL set_scalar_indices_from_config( id , idum1 , idum2 )
  1165. num_bytes_allocated = 0
  1166. ! now separate modules to reduce the size of module_domain that the compiler sees
  1167. CALL alloc_space_field_core_0 ( grid, id, setinitval_in , tl_in , inter_domain_in , num_bytes_allocated , &
  1168. sd31, ed31, sd32, ed32, sd33, ed33, &
  1169. sm31 , em31 , sm32 , em32 , sm33 , em33 , &
  1170. sp31 , ep31 , sp32 , ep32 , sp33 , ep33 , &
  1171. sp31x, ep31x, sp32x, ep32x, sp33x, ep33x, &
  1172. sp31y, ep31y, sp32y, ep32y, sp33y, ep33y, &
  1173. sm31x, em31x, sm32x, em32x, sm33x, em33x, &
  1174. sm31y, em31y, sm32y, em32y, sm33y, em33y )
  1175. CALL alloc_space_field_core_1 ( grid, id, setinitval_in , tl_in , inter_domain_in , num_bytes_allocated , &
  1176. sd31, ed31, sd32, ed32, sd33, ed33, &
  1177. sm31 , em31 , sm32 , em32 , sm33 , em33 , &
  1178. sp31 , ep31 , sp32 , ep32 , sp33 , ep33 , &
  1179. sp31x, ep31x, sp32x, ep32x, sp33x, ep33x, &
  1180. sp31y, ep31y, sp32y, ep32y, sp33y, ep33y, &
  1181. sm31x, em31x, sm32x, em32x, sm33x, em33x, &
  1182. sm31y, em31y, sm32y, em32y, sm33y, em33y )
  1183. CALL alloc_space_field_core_2 ( grid, id, setinitval_in , tl_in , inter_domain_in , num_bytes_allocated , &
  1184. sd31, ed31, sd32, ed32, sd33, ed33, &
  1185. sm31 , em31 , sm32 , em32 , sm33 , em33 , &
  1186. sp31 , ep31 , sp32 , ep32 , sp33 , ep33 , &
  1187. sp31x, ep31x, sp32x, ep32x, sp33x, ep33x, &
  1188. sp31y, ep31y, sp32y, ep32y, sp33y, ep33y, &
  1189. sm31x, em31x, sm32x, em32x, sm33x, em33x, &
  1190. sm31y, em31y, sm32y, em32y, sm33y, em33y )
  1191. CALL alloc_space_field_core_3 ( grid, id, setinitval_in , tl_in , inter_domain_in , num_bytes_allocated , &
  1192. sd31, ed31, sd32, ed32, sd33, ed33, &
  1193. sm31 , em31 , sm32 , em32 , sm33 , em33 , &
  1194. sp31 , ep31 , sp32 , ep32 , sp33 , ep33 , &
  1195. sp31x, ep31x, sp32x, ep32x, sp33x, ep33x, &
  1196. sp31y, ep31y, sp32y, ep32y, sp33y, ep33y, &
  1197. sm31x, em31x, sm32x, em32x, sm33x, em33x, &
  1198. sm31y, em31y, sm32y, em32y, sm33y, em33y )
  1199. CALL alloc_space_field_core_4 ( grid, id, setinitval_in , tl_in , inter_domain_in , num_bytes_allocated , &
  1200. sd31, ed31, sd32, ed32, sd33, ed33, &
  1201. sm31 , em31 , sm32 , em32 , sm33 , em33 , &
  1202. sp31 , ep31 , sp32 , ep32 , sp33 , ep33 , &
  1203. sp31x, ep31x, sp32x, ep32x, sp33x, ep33x, &
  1204. sp31y, ep31y, sp32y, ep32y, sp33y, ep33y, &
  1205. sm31x, em31x, sm32x, em32x, sm33x, em33x, &
  1206. sm31y, em31y, sm32y, em32y, sm33y, em33y )
  1207. CALL alloc_space_field_core_5 ( grid, id, setinitval_in , tl_in , inter_domain_in , num_bytes_allocated , &
  1208. sd31, ed31, sd32, ed32, sd33, ed33, &
  1209. sm31 , em31 , sm32 , em32 , sm33 , em33 , &
  1210. sp31 , ep31 , sp32 , ep32 , sp33 , ep33 , &
  1211. sp31x, ep31x, sp32x, ep32x, sp33x, ep33x, &
  1212. sp31y, ep31y, sp32y, ep32y, sp33y, ep33y, &
  1213. sm31x, em31x, sm32x, em32x, sm33x, em33x, &
  1214. sm31y, em31y, sm32y, em32y, sm33y, em33y )
  1215. CALL alloc_space_field_core_6 ( grid, id, setinitval_in , tl_in , inter_domain_in , num_bytes_allocated , &
  1216. sd31, ed31, sd32, ed32, sd33, ed33, &
  1217. sm31 , em31 , sm32 , em32 , sm33 , em33 , &
  1218. sp31 , ep31 , sp32 , ep32 , sp33 , ep33 , &
  1219. sp31x, ep31x, sp32x, ep32x, sp33x, ep33x, &
  1220. sp31y, ep31y, sp32y, ep32y, sp33y, ep33y, &
  1221. sm31x, em31x, sm32x, em32x, sm33x, em33x, &
  1222. sm31y, em31y, sm32y, em32y, sm33y, em33y )
  1223. CALL alloc_space_field_core_7 ( grid, id, setinitval_in , tl_in , inter_domain_in , num_bytes_allocated , &
  1224. sd31, ed31, sd32, ed32, sd33, ed33, &
  1225. sm31 , em31 , sm32 , em32 , sm33 , em33 , &
  1226. sp31 , ep31 , sp32 , ep32 , sp33 , ep33 , &
  1227. sp31x, ep31x, sp32x, ep32x, sp33x, ep33x, &
  1228. sp31y, ep31y, sp32y, ep32y, sp33y, ep33y, &
  1229. sm31x, em31x, sm32x, em32x, sm33x, em33x, &
  1230. sm31y, em31y, sm32y, em32y, sm33y, em33y )
  1231. CALL alloc_space_field_core_8 ( grid, id, setinitval_in , tl_in , inter_domain_in , num_bytes_allocated , &
  1232. sd31, ed31, sd32, ed32, sd33, ed33, &
  1233. sm31 , em31 , sm32 , em32 , sm33 , em33 , &
  1234. sp31 , ep31 , sp32 , ep32 , sp33 , ep33 , &
  1235. sp31x, ep31x, sp32x, ep32x, sp33x, ep33x, &
  1236. sp31y, ep31y, sp32y, ep32y, sp33y, ep33y, &
  1237. sm31x, em31x, sm32x, em32x, sm33x, em33x, &
  1238. sm31y, em31y, sm32y, em32y, sm33y, em33y )
  1239. CALL alloc_space_field_core_9 ( grid, id, setinitval_in , tl_in , inter_domain_in , num_bytes_allocated , &
  1240. sd31, ed31, sd32, ed32, sd33, ed33, &
  1241. sm31 , em31 , sm32 , em32 , sm33 , em33 , &
  1242. sp31 , ep31 , sp32 , ep32 , sp33 , ep33 , &
  1243. sp31x, ep31x, sp32x, ep32x, sp33x, ep33x, &
  1244. sp31y, ep31y, sp32y, ep32y, sp33y, ep33y, &
  1245. sm31x, em31x, sm32x, em32x, sm33x, em33x, &
  1246. sm31y, em31y, sm32y, em32y, sm33y, em33y )
  1247. IF ( .NOT. grid%have_displayed_alloc_stats ) THEN
  1248. ! we do not want to see this message more than once, as can happen with the allocation and
  1249. ! deallocation of intermediate domains used in nesting.
  1250. WRITE(wrf_err_message,*)&
  1251. 'alloc_space_field: domain ',id,', ',num_bytes_allocated,' bytes allocated'
  1252. CALL wrf_debug( 0, wrf_err_message )
  1253. grid%have_displayed_alloc_stats = .TRUE.
  1254. ENDIF
  1255. grid%alloced_sd31=sd31
  1256. grid%alloced_ed31=ed31
  1257. grid%alloced_sd32=sd32
  1258. grid%alloced_ed32=ed32
  1259. grid%alloced_sd33=sd33
  1260. grid%alloced_ed33=ed33
  1261. grid%alloced_sm31=sm31
  1262. grid%alloced_em31=em31
  1263. grid%alloced_sm32=sm32
  1264. grid%alloced_em32=em32
  1265. grid%alloced_sm33=sm33
  1266. grid%alloced_em33=em33
  1267. grid%alloced_sm31x=sm31x
  1268. grid%alloced_em31x=em31x
  1269. grid%alloced_sm32x=sm32x
  1270. grid%alloced_em32x=em32x
  1271. grid%alloced_sm33x=sm33x
  1272. grid%alloced_em33x=em33x
  1273. grid%alloced_sm31y=sm31y
  1274. grid%alloced_em31y=em31y
  1275. grid%alloced_sm32y=sm32y
  1276. grid%alloced_em32y=em32y
  1277. grid%alloced_sm33y=sm33y
  1278. grid%alloced_em33y=em33y
  1279. grid%allocated=.TRUE.
  1280. END SUBROUTINE alloc_space_field
  1281. ! Ensure_space_field allocates a grid's arrays if they are not yet
  1282. ! allocated. If they were already allocated, then it deallocates and
  1283. ! reallocates them if they were allocated with different dimensions.
  1284. ! If they were already allocated with the requested dimensions, then
  1285. ! ensure_space_field does nothing.
  1286. SUBROUTINE ensure_space_field ( grid, id, setinitval_in , tl_in , inter_domain_in , &
  1287. sd31, ed31, sd32, ed32, sd33, ed33, &
  1288. sm31 , em31 , sm32 , em32 , sm33 , em33 , &
  1289. sp31 , ep31 , sp32 , ep32 , sp33 , ep33 , &
  1290. sp31x, ep31x, sp32x, ep32x, sp33x, ep33x, &
  1291. sp31y, ep31y, sp32y, ep32y, sp33y, ep33y, &
  1292. sm31x, em31x, sm32x, em32x, sm33x, em33x, &
  1293. sm31y, em31y, sm32y, em32y, sm33y, em33y )
  1294. IMPLICIT NONE
  1295. ! Input data.
  1296. TYPE(domain) , POINTER :: grid
  1297. INTEGER , INTENT(IN) :: id
  1298. INTEGER , INTENT(IN) :: setinitval_in ! 3 = everything, 1 = arrays only, 0 = none
  1299. INTEGER , INTENT(IN) :: sd31, ed31, sd32, ed32, sd33, ed33
  1300. INTEGER , INTENT(IN) :: sm31, em31, sm32, em32, sm33, em33
  1301. INTEGER , INTENT(IN) :: sp31, ep31, sp32, ep32, sp33, ep33
  1302. INTEGER , INTENT(IN) :: sp31x, ep31x, sp32x, ep32x, sp33x, ep33x
  1303. INTEGER , INTENT(IN) :: sp31y, ep31y, sp32y, ep32y, sp33y, ep33y
  1304. INTEGER , INTENT(IN) :: sm31x, em31x, sm32x, em32x, sm33x, em33x
  1305. INTEGER , INTENT(IN) :: sm31y, em31y, sm32y, em32y, sm33y, em33y
  1306. ! this argument is a bitmask. First bit is time level 1, second is time level 2, and so on.
  1307. ! e.g. to set both 1st and second time level, use 3
  1308. ! to set only 1st use 1
  1309. ! to set only 2st use 2
  1310. INTEGER , INTENT(IN) :: tl_in
  1311. ! true if the allocation is for an intermediate domain (for nesting); only certain fields allocated
  1312. ! false otherwise (all allocated, modulo tl above)
  1313. LOGICAL , INTENT(IN) :: inter_domain_in
  1314. LOGICAL :: size_changed
  1315. size_changed= .not. ( &
  1316. grid%alloced_sd31 .eq. sd31 .and. grid%alloced_ed31 .eq. ed31 .and. &
  1317. grid%alloced_sd32 .eq. sd32 .and. grid%alloced_ed32 .eq. ed32 .and. &
  1318. grid%alloced_sd33 .eq. sd33 .and. grid%alloced_ed33 .eq. ed33 .and. &
  1319. grid%alloced_sm31 .eq. sm31 .and. grid%alloced_em31 .eq. em31 .and. &
  1320. grid%alloced_sm32 .eq. sm32 .and. grid%alloced_em32 .eq. em32 .and. &
  1321. grid%alloced_sm33 .eq. sm33 .and. grid%alloced_em33 .eq. em33 .and. &
  1322. grid%alloced_sm31x .eq. sm31x .and. grid%alloced_em31x .eq. em31x .and. &
  1323. grid%alloced_sm32x .eq. sm32x .and. grid%alloced_em32x .eq. em32x .and. &
  1324. grid%alloced_sm33x .eq. sm33x .and. grid%alloced_em33x .eq. em33x .and. &
  1325. grid%alloced_sm31y .eq. sm31y .and. grid%alloced_em31y .eq. em31y .and. &
  1326. grid%alloced_sm32y .eq. sm32y .and. grid%alloced_em32y .eq. em32y .and. &
  1327. grid%alloced_sm33y .eq. sm33y .and. grid%alloced_em33y .eq. em33y &
  1328. )
  1329. if(.not. grid%allocated .or. size_changed) then
  1330. if(.not. grid%allocated) then
  1331. call wrf_debug(1,'ensure_space_field: calling alloc_space_field because a grid was not allocated.')
  1332. else
  1333. if(size_changed) &
  1334. call wrf_debug(1,'ensure_space_field: deallocating and reallocating a grid because grid size changed.')
  1335. end if
  1336. if(grid%allocated) &
  1337. call dealloc_space_field( grid )
  1338. call alloc_space_field ( grid, id, setinitval_in , tl_in , inter_domain_in , &
  1339. sd31, ed31, sd32, ed32, sd33, ed33, &
  1340. sm31 , em31 , sm32 , em32 , sm33 , em33 , &
  1341. sp31 , ep31 , sp32 , ep32 , sp33 , ep33 , &
  1342. sp31x, ep31x, sp32x, ep32x, sp33x, ep33x, &
  1343. sp31y, ep31y, sp32y, ep32y, sp33y, ep33y, &
  1344. sm31x, em31x, sm32x, em32x, sm33x, em33x, &
  1345. sm31y, em31y, sm32y, em32y, sm33y, em33y )
  1346. end if
  1347. END SUBROUTINE ensure_space_field
  1348. ! This routine is used to DEALLOCATE space for a single domain and remove
  1349. ! it from the linked list. First the pointers in the linked list are fixed
  1350. ! (so the one in the middle can be removed). Then the domain itself is
  1351. ! DEALLOCATEd via a call to domain_destroy().
  1352. SUBROUTINE dealloc_space_domain ( id )
  1353. IMPLICIT NONE
  1354. ! Input data.
  1355. INTEGER , INTENT(IN) :: id
  1356. ! Local data.
  1357. TYPE(domain) , POINTER :: grid
  1358. LOGICAL :: found
  1359. ! Initializations required to start the routine.
  1360. grid => head_grid
  1361. old_grid => head_grid
  1362. found = .FALSE.
  1363. ! The identity of the domain to delete is based upon the "id".
  1364. ! We search all of the possible grids. It is required to find a domain
  1365. ! otherwise it is a fatal error.
  1366. find_grid : DO WHILE ( ASSOCIATED(grid) )
  1367. IF ( grid%id == id ) THEN
  1368. found = .TRUE.
  1369. old_grid%next => grid%next
  1370. CALL domain_destroy( grid )
  1371. EXIT find_grid
  1372. END IF
  1373. old_grid => grid
  1374. grid => grid%next
  1375. END DO find_grid
  1376. IF ( .NOT. found ) THEN
  1377. WRITE ( wrf_err_message , * ) 'module_domain: ', &
  1378. 'dealloc_space_domain: Could not de-allocate grid id ',id
  1379. CALL wrf_error_fatal ( TRIM( wrf_err_message ) )
  1380. END IF
  1381. END SUBROUTINE dealloc_space_domain
  1382. ! This routine is used to DEALLOCATE space for a single domain type.
  1383. ! First, the field data are all removed through a CALL to the
  1384. ! dealloc_space_field routine. Then the pointer to the domain
  1385. ! itself is DEALLOCATEd.
  1386. SUBROUTINE domain_destroy ( grid )
  1387. IMPLICIT NONE
  1388. ! Input data.
  1389. TYPE(domain) , POINTER :: grid
  1390. CALL dealloc_space_field ( grid )
  1391. CALL dealloc_linked_lists( grid )
  1392. DEALLOCATE( grid%parents )
  1393. DEALLOCATE( grid%nests )
  1394. ! clean up time manager bits
  1395. CALL domain_clock_destroy( grid )
  1396. CALL domain_alarms_destroy( grid )
  1397. IF ( ASSOCIATED( grid%i_start ) ) THEN
  1398. DEALLOCATE( grid%i_start )
  1399. ENDIF
  1400. IF ( ASSOCIATED( grid%i_end ) ) THEN
  1401. DEALLOCATE( grid%i_end )
  1402. ENDIF
  1403. IF ( ASSOCIATED( grid%j_start ) ) THEN
  1404. DEALLOCATE( grid%j_start )
  1405. ENDIF
  1406. IF ( ASSOCIATED( grid%j_end ) ) THEN
  1407. DEALLOCATE( grid%j_end )
  1408. ENDIF
  1409. IF ( ASSOCIATED( grid%itsloc ) ) THEN
  1410. DEALLOCATE( grid%itsloc )
  1411. ENDIF
  1412. IF ( ASSOCIATED( grid%jtsloc ) ) THEN
  1413. DEALLOCATE( grid%jtsloc )
  1414. ENDIF
  1415. IF ( ASSOCIATED( grid%id_tsloc ) ) THEN
  1416. DEALLOCATE( grid%id_tsloc )
  1417. ENDIF
  1418. IF ( ASSOCIATED( grid%lattsloc ) ) THEN
  1419. DEALLOCATE( grid%lattsloc )
  1420. ENDIF
  1421. IF ( ASSOCIATED( grid%lontsloc ) ) THEN
  1422. DEALLOCATE( grid%lontsloc )
  1423. ENDIF
  1424. IF ( ASSOCIATED( grid%nametsloc ) ) THEN
  1425. DEALLOCATE( grid%nametsloc )
  1426. ENDIF
  1427. IF ( ASSOCIATED( grid%desctsloc ) ) THEN
  1428. DEALLOCATE( grid%desctsloc )
  1429. ENDIF
  1430. IF ( ASSOCIATED( grid%ts_filename ) ) THEN
  1431. DEALLOCATE( grid%ts_filename )
  1432. ENDIF
  1433. #if (EM_CORE == 1)
  1434. IF ( ASSOCIATED( grid%track_time_in ) ) THEN
  1435. DEALLOCATE( grid%track_time_in )
  1436. ENDIF
  1437. IF ( ASSOCIATED( grid%track_lat_in ) ) THEN
  1438. DEALLOCATE( grid%track_lat_in )
  1439. ENDIF
  1440. IF ( ASSOCIATED( grid%track_lon_in ) ) THEN
  1441. DEALLOCATE( grid%track_lon_in )
  1442. ENDIF
  1443. IF ( ASSOCIATED( grid%track_i ) ) THEN
  1444. DEALLOCATE( grid%track_i )
  1445. ENDIF
  1446. IF ( ASSOCIATED( grid%track_j ) ) THEN
  1447. DEALLOCATE( grid%track_j )
  1448. ENDIF
  1449. IF ( ASSOCIATED( grid%track_time_domain ) ) THEN
  1450. DEALLOCATE( grid%track_time_domain )
  1451. ENDIF
  1452. IF ( ASSOCIATED( grid%track_lat_domain ) ) THEN
  1453. DEALLOCATE( grid%track_lat_domain )
  1454. ENDIF
  1455. IF ( ASSOCIATED( grid%track_lon_domain ) ) THEN
  1456. DEALLOCATE( grid%track_lon_domain )
  1457. ENDIF
  1458. #endif
  1459. DEALLOCATE( grid )
  1460. NULLIFY( grid )
  1461. END SUBROUTINE domain_destroy
  1462. SUBROUTINE dealloc_linked_lists ( grid )
  1463. IMPLICIT NONE
  1464. TYPE(domain), POINTER :: grid
  1465. TYPE(fieldlist), POINTER :: p, q
  1466. p => grid%head_statevars
  1467. DO WHILE ( ASSOCIATED( p ) )
  1468. q => p ; p => p%next ; DEALLOCATE(q)
  1469. ENDDO
  1470. NULLIFY(grid%head_statevars) ; NULLIFY( grid%tail_statevars)
  1471. #if (DA_CORE != 1)
  1472. IF ( .NOT. grid%is_intermediate ) THEN
  1473. ALLOCATE( grid%head_statevars )
  1474. NULLIFY( grid%head_statevars%next)
  1475. grid%tail_statevars => grid%head_statevars
  1476. ENDIF
  1477. #endif
  1478. END SUBROUTINE dealloc_linked_lists
  1479. RECURSIVE SUBROUTINE show_nest_subtree ( grid )
  1480. TYPE(domain), POINTER :: grid
  1481. INTEGER myid
  1482. INTEGER kid
  1483. IF ( .NOT. ASSOCIATED( grid ) ) RETURN
  1484. myid = grid%id
  1485. write(0,*)'show_nest_subtree ',myid
  1486. DO kid = 1, max_nests
  1487. IF ( ASSOCIATED( grid%nests(kid)%ptr ) ) THEN
  1488. IF ( grid%nests(kid)%ptr%id .EQ. myid ) THEN
  1489. CALL wrf_error_fatal( 'show_nest_subtree: nest hierarchy corrupted' )
  1490. ENDIF
  1491. CALL show_nest_subtree( grid%nests(kid)%ptr )
  1492. ENDIF
  1493. ENDDO
  1494. END SUBROUTINE show_nest_subtree
  1495. !
  1496. ! This routine DEALLOCATEs each gridded field for this domain. For each type of
  1497. ! different array (1d, 2d, 3d, etc.), the space for each pointer is DEALLOCATEd
  1498. ! for every -1 (i.e., each different meteorological field).
  1499. SUBROUTINE dealloc_space_field ( grid )
  1500. IMPLICIT NONE
  1501. ! Input data.
  1502. TYPE(domain) , POINTER :: grid
  1503. ! Local data.
  1504. INTEGER :: ierr
  1505. # include <deallocs.inc>
  1506. END SUBROUTINE dealloc_space_field
  1507. !
  1508. !
  1509. RECURSIVE SUBROUTINE find_grid_by_id ( id, in_grid, result_grid )
  1510. IMPLICIT NONE
  1511. INTEGER, INTENT(IN) :: id
  1512. TYPE(domain), POINTER :: in_grid
  1513. TYPE(domain), POINTER :: result_grid
  1514. ! <DESCRIPTION>
  1515. ! This is a recursive subroutine that traverses the domain hierarchy rooted
  1516. ! at the input argument <em>in_grid</em>, a pointer to TYPE(domain), and returns
  1517. ! a pointer to the domain matching the integer argument <em>id</em> if it exists.
  1518. !
  1519. ! </DESCRIPTION>
  1520. TYPE(domain), POINTER :: grid_ptr
  1521. INTEGER :: kid
  1522. LOGICAL :: found
  1523. found = .FALSE.
  1524. NULLIFY(result_grid)
  1525. IF ( ASSOCIATED( in_grid ) ) THEN
  1526. IF ( in_grid%id .EQ. id ) THEN
  1527. result_grid => in_grid
  1528. ELSE
  1529. grid_ptr => in_grid
  1530. DO WHILE ( ASSOCIATED( grid_ptr ) .AND. .NOT. found )
  1531. DO kid = 1, max_nests
  1532. IF ( ASSOCIATED( grid_ptr%nests(kid)%ptr ) .AND. .NOT. found ) THEN
  1533. CALL find_grid_by_id ( id, grid_ptr%nests(kid)%ptr, result_grid )
  1534. IF ( ASSOCIATED( result_grid ) ) THEN
  1535. IF ( result_grid%id .EQ. id ) found = .TRUE.
  1536. ENDIF
  1537. ENDIF
  1538. ENDDO
  1539. IF ( .NOT. found ) grid_ptr => grid_ptr%sibling
  1540. ENDDO
  1541. ENDIF
  1542. ENDIF
  1543. RETURN
  1544. END SUBROUTINE find_grid_by_id
  1545. FUNCTION first_loc_integer ( array , search ) RESULT ( loc )
  1546. IMPLICIT NONE
  1547. ! Input data.
  1548. INTEGER , INTENT(IN) , DIMENSION(:) :: array
  1549. INTEGER , INTENT(IN) :: search
  1550. ! Output data.
  1551. INTEGER :: loc
  1552. !<DESCRIPTION>
  1553. ! This routine is used to find a specific domain identifier in an array
  1554. ! of domain identifiers.
  1555. !
  1556. !</DESCRIPTION>
  1557. ! Local data.
  1558. INTEGER :: loop
  1559. loc = -1
  1560. find : DO loop = 1 , SIZE(array)
  1561. IF ( search == array(loop) ) THEN
  1562. loc = loop
  1563. EXIT find
  1564. END IF
  1565. END DO find
  1566. END FUNCTION first_loc_integer
  1567. !
  1568. SUBROUTINE init_module_domain
  1569. END SUBROUTINE init_module_domain
  1570. ! <DESCRIPTION>
  1571. !
  1572. ! The following routines named domain_*() are convenience routines that
  1573. ! eliminate many duplicated bits of code. They provide shortcuts for the
  1574. ! most common operations on the domain_clock field of TYPE(domain).
  1575. !
  1576. ! </DESCRIPTION>
  1577. FUNCTION domain_get_current_time ( grid ) RESULT ( current_time )
  1578. IMPLICIT NONE
  1579. ! <DESCRIPTION>
  1580. ! This convenience function returns the current time for domain grid.
  1581. !
  1582. ! </DESCRIPTION>
  1583. TYPE(domain), INTENT(IN) :: grid
  1584. ! result
  1585. TYPE(WRFU_Time) :: current_time
  1586. ! locals
  1587. INTEGER :: rc
  1588. CALL WRFU_ClockGet( grid%domain_clock, CurrTime=current_time, &
  1589. rc=rc )
  1590. IF ( rc /= WRFU_SUCCESS ) THEN
  1591. CALL wrf_error_fatal ( &
  1592. 'domain_get_current_time: WRFU_ClockGet failed' )
  1593. ENDIF
  1594. END FUNCTION domain_get_current_time
  1595. FUNCTION domain_get_start_time ( grid ) RESULT ( start_time )
  1596. IMPLICIT NONE
  1597. ! <DESCRIPTION>
  1598. ! This convenience function returns the start time for domain grid.
  1599. !
  1600. ! </DESCRIPTION>
  1601. TYPE(domain), INTENT(IN) :: grid
  1602. ! result
  1603. TYPE(WRFU_Time) :: start_time
  1604. ! locals
  1605. INTEGER :: rc
  1606. CALL WRFU_ClockGet( grid%domain_clock, StartTime=start_time, &
  1607. rc=rc )
  1608. IF ( rc /= WRFU_SUCCESS ) THEN
  1609. CALL wrf_error_fatal ( &
  1610. 'domain_get_start_time: WRFU_ClockGet failed' )
  1611. ENDIF
  1612. END FUNCTION domain_get_start_time
  1613. FUNCTION domain_get_stop_time ( grid ) RESULT ( stop_time )
  1614. IMPLICIT NONE
  1615. ! <DESCRIPTION>
  1616. ! This convenience function returns the stop time for domain grid.
  1617. !
  1618. ! </DESCRIPTION>
  1619. TYPE(domain), INTENT(IN) :: grid
  1620. ! result
  1621. TYPE(WRFU_Time) :: stop_time
  1622. ! locals
  1623. INTEGER :: rc
  1624. CALL WRFU_ClockGet( grid%domain_clock, StopTime=stop_time, &
  1625. rc=rc )
  1626. IF ( rc /= WRFU_SUCCESS ) THEN
  1627. CALL wrf_error_fatal ( &
  1628. 'domain_get_stop_time: WRFU_ClockGet failed' )
  1629. ENDIF
  1630. END FUNCTION domain_get_stop_time
  1631. FUNCTION domain_get_time_step ( grid ) RESULT ( time_step )
  1632. IMPLICIT NONE
  1633. ! <DESCRIPTION>
  1634. ! This convenience function returns the time step for domain grid.
  1635. !
  1636. ! </DESCRIPTION>
  1637. TYPE(domain), INTENT(IN) :: grid
  1638. ! result
  1639. TYPE(WRFU_TimeInterval) :: time_step
  1640. ! locals
  1641. INTEGER :: rc
  1642. CALL WRFU_ClockGet( grid%domain_clock, timeStep=time_step, &
  1643. rc=rc )
  1644. IF ( rc /= WRFU_SUCCESS ) THEN
  1645. CALL wrf_error_fatal ( &
  1646. 'domain_get_time_step: WRFU_ClockGet failed' )
  1647. ENDIF
  1648. END FUNCTION domain_get_time_step
  1649. FUNCTION domain_get_advanceCount ( grid ) RESULT ( advanceCount )
  1650. IMPLICIT NONE
  1651. ! <DESCRIPTION>
  1652. ! This convenience function returns the time step for domain grid.
  1653. ! Also converts from INTEGER(WRFU_KIND_I8) to INTEGER.
  1654. !
  1655. ! </DESCRIPTION>
  1656. TYPE(domain), INTENT(IN) :: grid
  1657. ! result
  1658. INTEGER :: advanceCount
  1659. ! locals
  1660. INTEGER(WRFU_KIND_I8) :: advanceCountLcl
  1661. INTEGER :: rc
  1662. CALL WRFU_ClockGet( grid%domain_clock, &
  1663. advanceCount=advanceCountLcl, &
  1664. rc=rc )
  1665. IF ( rc /= WRFU_SUCCESS ) THEN
  1666. CALL wrf_error_fatal ( &
  1667. 'domain_get_advanceCount: WRFU_ClockGet failed' )
  1668. ENDIF
  1669. advanceCount = advanceCountLcl
  1670. END FUNCTION domain_get_advanceCount
  1671. SUBROUTINE domain_alarms_destroy ( grid )
  1672. IMPLICIT NONE
  1673. ! <DESCRIPTION>
  1674. ! This convenience routine destroys and deallocates all alarms associated
  1675. ! with grid.
  1676. !
  1677. ! </DESCRIPTION>
  1678. TYPE(domain), INTENT(INOUT) :: grid
  1679. ! Local data.
  1680. INTEGER :: alarmid
  1681. IF ( ASSOCIATED( grid%alarms ) .AND. &
  1682. ASSOCIATED( grid%alarms_created ) ) THEN
  1683. DO alarmid = 1, MAX_WRF_ALARMS
  1684. IF ( grid%alarms_created( alarmid ) ) THEN
  1685. CALL WRFU_AlarmDestroy( grid%alarms( alarmid ) )
  1686. grid%alarms_created( alarmid ) = .FALSE.
  1687. ENDIF
  1688. ENDDO
  1689. DEALLOCATE( grid%alarms )
  1690. NULLIFY( grid%alarms )
  1691. DEALLOCATE( grid%alarms_created )
  1692. NULLIFY( grid%alarms_created )
  1693. ENDIF
  1694. END SUBROUTINE domain_alarms_destroy
  1695. SUBROUTINE domain_clock_destroy ( grid )
  1696. IMPLICIT NONE
  1697. ! <DESCRIPTION>
  1698. ! This convenience routine destroys and deallocates the domain clock.
  1699. !
  1700. ! </DESCRIPTION>
  1701. TYPE(domain), INTENT(INOUT) :: grid
  1702. IF ( ASSOCIATED( grid%domain_clock ) ) THEN
  1703. IF ( grid%domain_clock_created ) THEN
  1704. CALL WRFU_ClockDestroy( grid%domain_clock )
  1705. grid%domain_clock_created = .FALSE.
  1706. ENDIF
  1707. DEALLOCATE( grid%domain_clock )
  1708. NULLIFY( grid%domain_clock )
  1709. ENDIF
  1710. END SUBROUTINE domain_clock_destroy
  1711. FUNCTION domain_last_time_step ( grid ) RESULT ( LAST_TIME )
  1712. IMPLICIT NONE
  1713. ! <DESCRIPTION>
  1714. ! This convenience function returns .TRUE. if this is the last time
  1715. ! step for domain grid. Thanks to Tom Black.
  1716. !
  1717. ! </DESCRIPTION>
  1718. TYPE(domain), INTENT(IN) :: grid
  1719. ! result
  1720. LOGICAL :: LAST_TIME
  1721. LAST_TIME = domain_get_stop_time( grid ) .EQ. &
  1722. ( domain_get_current_time( grid ) + &
  1723. domain_get_time_step( grid ) )
  1724. END FUNCTION domain_last_time_step
  1725. FUNCTION domain_clockisstoptime ( grid ) RESULT ( is_stop_time )
  1726. IMPLICIT NONE
  1727. ! <DESCRIPTION>
  1728. ! This convenience function returns .TRUE. iff grid%clock has reached its
  1729. ! stop time.
  1730. !
  1731. ! </DESCRIPTION>
  1732. TYPE(domain), INTENT(IN) :: grid
  1733. ! result
  1734. LOGICAL :: is_stop_time
  1735. INTEGER :: rc
  1736. is_stop_time = WRFU_ClockIsStopTime( grid%domain_clock , rc=rc )
  1737. IF ( rc /= WRFU_SUCCESS ) THEN
  1738. CALL wrf_error_fatal ( &
  1739. 'domain_clockisstoptime: WRFU_ClockIsStopTime() failed' )
  1740. ENDIF
  1741. END FUNCTION domain_clockisstoptime
  1742. FUNCTION domain_clockisstopsubtime ( grid ) RESULT ( is_stop_subtime )
  1743. IMPLICIT NONE
  1744. ! <DESCRIPTION>
  1745. ! This convenience function returns .TRUE. iff grid%clock has reached its
  1746. ! grid%stop_subtime.
  1747. !
  1748. ! </DESCRIPTION>
  1749. TYPE(domain), INTENT(IN) :: grid
  1750. ! result
  1751. LOGICAL :: is_stop_subtime
  1752. INTEGER :: rc
  1753. TYPE(WRFU_TimeInterval) :: timeStep
  1754. TYPE(WRFU_Time) :: currentTime
  1755. LOGICAL :: positive_timestep
  1756. is_stop_subtime = .FALSE.
  1757. CALL domain_clock_get( grid, time_step=timeStep, &
  1758. current_time=currentTime )
  1759. positive_timestep = ESMF_TimeIntervalIsPositive( timeStep )
  1760. IF ( positive_timestep ) THEN
  1761. ! hack for bug in PGI 5.1-x
  1762. ! IF ( currentTime .GE. grid%stop_subtime ) THEN
  1763. IF ( ESMF_TimeGE( currentTime, grid%stop_subtime ) ) THEN
  1764. is_stop_subtime = .TRUE.
  1765. ENDIF
  1766. ELSE
  1767. ! hack for bug in PGI 5.1-x
  1768. ! IF ( currentTime .LE. grid%stop_subtime ) THEN
  1769. IF ( ESMF_TimeLE( currentTime, grid%stop_subtime ) ) THEN
  1770. is_stop_subtime = .TRUE.
  1771. ENDIF
  1772. ENDIF
  1773. END FUNCTION domain_clockisstopsubtime
  1774. FUNCTION domain_get_sim_start_time ( grid ) RESULT ( simulationStartTime )
  1775. IMPLICIT NONE
  1776. ! <DESCRIPTION>
  1777. ! This convenience routine returns simulation start time for domain grid as
  1778. ! a time instant.
  1779. !
  1780. ! If this is not a restart run, the start_time of head_grid%clock is returned
  1781. ! instead.
  1782. !
  1783. ! Note that simulation start time remains constant through restarts while
  1784. ! the start_time of head_grid%clock always refers to the start time of the
  1785. ! current run (restart or otherwise).
  1786. !
  1787. ! </DESCRIPTION>
  1788. TYPE(domain), INTENT(IN) :: grid
  1789. ! result
  1790. TYPE(WRFU_Time) :: simulationStartTime
  1791. ! Locals
  1792. INTEGER :: rc
  1793. INTEGER :: simulation_start_year, simulation_start_month, &
  1794. simulation_start_day, simulation_start_hour , &
  1795. simulation_start_minute, simulation_start_second
  1796. CALL nl_get_simulation_start_year ( 1, simulation_start_year )
  1797. CALL nl_get_simulation_start_month ( 1, simulation_start_month )
  1798. CALL nl_get_simulation_start_day ( 1, simulation_start_day )
  1799. CALL nl_get_simulation_start_hour ( 1, simulation_start_hour )
  1800. CALL nl_get_simulation_start_minute ( 1, simulation_start_minute )
  1801. CALL nl_get_simulation_start_second ( 1, simulation_start_second )
  1802. CALL WRFU_TimeSet( simulationStartTime, &
  1803. YY=simulation_start_year, &
  1804. MM=simulation_start_month, &
  1805. DD=simulation_start_day, &
  1806. H=simulation_start_hour, &
  1807. M=simulation_start_minute, &
  1808. S=simulation_start_second, &
  1809. rc=rc )
  1810. IF ( rc /= WRFU_SUCCESS ) THEN
  1811. CALL nl_get_start_year ( 1, simulation_start_year )
  1812. CALL nl_get_start_month ( 1, simulation_start_month )
  1813. CALL nl_get_start_day ( 1, simulation_start_day )
  1814. CALL nl_get_start_hour ( 1, simulation_start_hour )
  1815. CALL nl_get_start_minute ( 1, simulation_start_minute )
  1816. CALL nl_get_start_second ( 1, simulation_start_second )
  1817. CALL wrf_debug( 150, "WARNING: domain_get_sim_start_time using head_grid start time from namelist" )
  1818. CALL WRFU_TimeSet( simulationStartTime, &
  1819. YY=simulation_start_year, &
  1820. MM=simulation_start_month, &
  1821. DD=simulation_start_day, &
  1822. H=simulation_start_hour, &
  1823. M=simulation_start_minute, &
  1824. S=simulation_start_second, &
  1825. rc=rc )
  1826. ENDIF
  1827. RETURN
  1828. END FUNCTION domain_get_sim_start_time
  1829. FUNCTION domain_get_time_since_sim_start ( grid ) RESULT ( time_since_sim_start )
  1830. IMPLICIT NONE
  1831. ! <DESCRIPTION>
  1832. ! This convenience function returns the time elapsed since start of
  1833. ! simulation for domain grid.
  1834. !
  1835. ! Note that simulation start time remains constant through restarts while
  1836. ! the start_time of grid%clock always refers to the start time of the
  1837. ! current run (restart or otherwise).
  1838. !
  1839. ! </DESCRIPTION>
  1840. TYPE(domain), INTENT(IN) :: grid
  1841. ! result
  1842. TYPE(WRFU_TimeInterval) :: time_since_sim_start
  1843. ! locals
  1844. TYPE(WRFU_Time) :: lcl_currtime, lcl_simstarttime
  1845. lcl_simstarttime = domain_get_sim_start_time( grid )
  1846. lcl_currtime = domain_get_current_time ( grid )
  1847. time_since_sim_start = lcl_currtime - lcl_simstarttime
  1848. END FUNCTION domain_get_time_since_sim_start
  1849. SUBROUTINE domain_clock_get( grid, current_time, &
  1850. current_timestr, &
  1851. current_timestr_frac, &
  1852. start_time, start_timestr, &
  1853. stop_time, stop_timestr, &
  1854. time_step, time_stepstr, &
  1855. time_stepstr_frac, &
  1856. advanceCount, &
  1857. currentDayOfYearReal, &
  1858. minutesSinceSimulationStart, &
  1859. timeSinceSimulationStart, &
  1860. simulationStartTime, &
  1861. simulationStartTimeStr )
  1862. IMPLICIT NONE
  1863. TYPE(domain), INTENT(IN) :: grid
  1864. TYPE(WRFU_Time), INTENT( OUT), OPTIONAL :: current_time
  1865. CHARACTER (LEN=*), INTENT( OUT), OPTIONAL :: current_timestr
  1866. CHARACTER (LEN=*), INTENT( OUT), OPTIONAL :: current_timestr_frac
  1867. TYPE(WRFU_Time), INTENT( OUT), OPTIONAL :: start_time
  1868. CHARACTER (LEN=*), INTENT( OUT), OPTIONAL :: start_timestr
  1869. TYPE(WRFU_Time), INTENT( OUT), OPTIONAL :: stop_time
  1870. CHARACTER (LEN=*), INTENT( OUT), OPTIONAL :: stop_timestr
  1871. TYPE(WRFU_TimeInterval), INTENT( OUT), OPTIONAL :: time_step
  1872. CHARACTER (LEN=*), INTENT( OUT), OPTIONAL :: time_stepstr
  1873. CHARACTER (LEN=*), INTENT( OUT), OPTIONAL :: time_stepstr_frac
  1874. INTEGER, INTENT( OUT), OPTIONAL :: advanceCount
  1875. ! currentDayOfYearReal = 0.0 at 0Z on 1 January, 0.5 at 12Z on
  1876. ! 1 January, etc.
  1877. REAL, INTENT( OUT), OPTIONAL :: currentDayOfYearReal
  1878. ! Time at which simulation started. If this is not a restart run,
  1879. ! start_time is returned instead.
  1880. TYPE(WRFU_Time), INTENT( OUT), OPTIONAL :: simulationStartTime
  1881. CHARACTER (LEN=*), INTENT( OUT), OPTIONAL :: simulationStartTimeStr
  1882. ! time interval since start of simulation, includes effects of
  1883. ! restarting even when restart uses a different timestep
  1884. TYPE(WRFU_TimeInterval), INTENT( OUT), OPTIONAL :: timeSinceSimulationStart
  1885. ! minutes since simulation start date
  1886. REAL, INTENT( OUT), OPTIONAL :: minutesSinceSimulationStart
  1887. ! <DESCRIPTION>
  1888. ! This convenience routine returns clock information for domain grid in
  1889. ! various forms. The caller is responsible for ensuring that character
  1890. ! string actual arguments are big enough.
  1891. !
  1892. ! </DESCRIPTION>
  1893. ! Locals
  1894. TYPE(WRFU_Time) :: lcl_currtime, lcl_stoptime, lcl_starttime
  1895. TYPE(WRFU_Time) :: lcl_simulationStartTime
  1896. TYPE(WRFU_TimeInterval) :: lcl_time_step, lcl_timeSinceSimulationStart
  1897. INTEGER :: days, seconds, Sn, Sd, rc
  1898. CHARACTER (LEN=256) :: tmp_str
  1899. CHARACTER (LEN=256) :: frac_str
  1900. REAL(WRFU_KIND_R8) :: currentDayOfYearR8
  1901. IF ( PRESENT( start_time ) ) THEN
  1902. start_time = domain_get_start_time ( grid )
  1903. ENDIF
  1904. IF ( PRESENT( start_timestr ) ) THEN
  1905. lcl_starttime = domain_get_start_time ( grid )
  1906. CALL wrf_timetoa ( lcl_starttime, start_timestr )
  1907. ENDIF
  1908. IF ( PRESENT( time_step ) ) THEN
  1909. time_step = domain_get_time_step ( grid )
  1910. ENDIF
  1911. IF ( PRESENT( time_stepstr ) ) THEN
  1912. lcl_time_step = domain_get_time_step ( grid )
  1913. CALL WRFU_TimeIntervalGet( lcl_time_step, &
  1914. timeString=time_stepstr, rc=rc )
  1915. IF ( rc /= WRFU_SUCCESS ) THEN
  1916. CALL wrf_error_fatal ( &
  1917. 'domain_clock_get: WRFU_TimeIntervalGet() failed' )
  1918. ENDIF
  1919. ENDIF
  1920. IF ( PRESENT( time_stepstr_frac ) ) THEN
  1921. lcl_time_step = domain_get_time_step ( grid )
  1922. CALL WRFU_TimeIntervalGet( lcl_time_step, timeString=tmp_str, &
  1923. Sn=Sn, Sd=Sd, rc=rc )
  1924. IF ( rc /= WRFU_SUCCESS ) THEN
  1925. CALL wrf_error_fatal ( &
  1926. 'domain_clock_get: WRFU_TimeIntervalGet() failed' )
  1927. ENDIF
  1928. CALL fraction_to_string( Sn, Sd, frac_str )
  1929. time_stepstr_frac = TRIM(tmp_str)//TRIM(frac_str)
  1930. ENDIF
  1931. IF ( PRESENT( advanceCount ) ) THEN
  1932. advanceCount = domain_get_advanceCount ( grid )
  1933. ENDIF
  1934. ! This duplication avoids assignment of time-manager objects
  1935. ! which works now in ESMF 2.2.0 but may not work in the future
  1936. ! if these objects become "deep". We have already been bitten
  1937. ! by this when the clock objects were changed from "shallow" to
  1938. ! "deep". Once again, adherence to orthodox canonical form by
  1939. ! ESMF would avoid all this crap.
  1940. IF ( PRESENT( current_time ) ) THEN
  1941. current_time = domain_get_current_time ( grid )
  1942. ENDIF
  1943. IF ( PRESENT( current_timestr ) ) THEN
  1944. lcl_currtime = domain_get_current_time ( grid )
  1945. CALL wrf_timetoa ( lcl_currtime, current_timestr )
  1946. ENDIF
  1947. ! current time string including fractional part, if present
  1948. IF ( PRESENT( current_timestr_frac ) ) THEN
  1949. lcl_currtime = domain_get_current_time ( grid )
  1950. CALL wrf_timetoa ( lcl_currtime, tmp_str )
  1951. CALL WRFU_TimeGet( lcl_currtime, Sn=Sn, Sd=Sd, rc=rc )
  1952. IF ( rc /= WRFU_SUCCESS ) THEN
  1953. CALL wrf_error_fatal ( &
  1954. 'domain_clock_get: WRFU_TimeGet() failed' )
  1955. ENDIF
  1956. CALL fraction_to_string( Sn, Sd, frac_str )
  1957. current_timestr_frac = TRIM(tmp_str)//TRIM(frac_str)
  1958. ENDIF
  1959. IF ( PRESENT( stop_time ) ) THEN
  1960. stop_time = domain_get_stop_time ( grid )
  1961. ENDIF
  1962. IF ( PRESENT( stop_timestr ) ) THEN
  1963. lcl_stoptime = domain_get_stop_time ( grid )
  1964. CALL wrf_timetoa ( lcl_stoptime, stop_timestr )
  1965. ENDIF
  1966. IF ( PRESENT( currentDayOfYearReal ) ) THEN
  1967. lcl_currtime = domain_get_current_time ( grid )
  1968. CALL WRFU_TimeGet( lcl_currtime, dayOfYear_r8=currentDayOfYearR8, &
  1969. rc=rc )
  1970. IF ( rc /= WRFU_SUCCESS ) THEN
  1971. CALL wrf_error_fatal ( &
  1972. 'domain_clock_get: WRFU_TimeGet(dayOfYear_r8) failed' )
  1973. ENDIF
  1974. currentDayOfYearReal = REAL( currentDayOfYearR8 ) - 1.0
  1975. ENDIF
  1976. IF ( PRESENT( simulationStartTime ) ) THEN
  1977. simulationStartTime = domain_get_sim_start_time( grid )
  1978. ENDIF
  1979. IF ( PRESENT( simulationStartTimeStr ) ) THEN
  1980. lcl_simulationStartTime = domain_get_sim_start_time( grid )
  1981. CALL wrf_timetoa ( lcl_simulationStartTime, simulationStartTimeStr )
  1982. ENDIF
  1983. IF ( PRESENT( timeSinceSimulationStart ) ) THEN
  1984. timeSinceSimulationStart = domain_get_time_since_sim_start( grid )
  1985. ENDIF
  1986. IF ( PRESENT( minutesSinceSimulationStart ) ) THEN
  1987. lcl_timeSinceSimulationStart = domain_get_time_since_sim_start( grid )
  1988. CALL WRFU_TimeIntervalGet( lcl_timeSinceSimulationStart, &
  1989. D=days, S=seconds, Sn=Sn, Sd=Sd, rc=rc )
  1990. IF ( rc /= WRFU_SUCCESS ) THEN
  1991. CALL wrf_error_fatal ( &
  1992. 'domain_clock_get: WRFU_TimeIntervalGet() failed' )
  1993. ENDIF
  1994. ! get rid of hard-coded constants
  1995. minutesSinceSimulationStart = ( REAL( days ) * 24. * 60. ) + &
  1996. ( REAL( seconds ) / 60. )
  1997. IF ( Sd /= 0 ) THEN
  1998. minutesSinceSimulationStart = minutesSinceSimulationStart + &
  1999. ( ( REAL( Sn ) / REAL( Sd ) ) / 60. )
  2000. ENDIF
  2001. ENDIF
  2002. RETURN
  2003. END SUBROUTINE domain_clock_get
  2004. FUNCTION domain_clockisstarttime ( grid ) RESULT ( is_start_time )
  2005. IMPLICIT NONE
  2006. ! <DESCRIPTION>
  2007. ! This convenience function returns .TRUE. iff grid%clock is at its
  2008. ! start time.
  2009. !
  2010. ! </DESCRIPTION>
  2011. TYPE(domain), INTENT(IN) :: grid
  2012. ! result
  2013. LOGICAL :: is_start_time
  2014. TYPE(WRFU_Time) :: start_time, current_time
  2015. CALL domain_clock_get( grid, current_time=current_time, &
  2016. start_time=start_time )
  2017. is_start_time = ( current_time == start_time )
  2018. END FUNCTION domain_clockisstarttime
  2019. FUNCTION domain_clockissimstarttime ( grid ) RESULT ( is_sim_start_time )
  2020. IMPLICIT NONE
  2021. ! <DESCRIPTION>
  2022. ! This convenience function returns .TRUE. iff grid%clock is at the
  2023. ! simulation start time. (It returns .FALSE. during a restart run.)
  2024. !
  2025. ! </DESCRIPTION>
  2026. TYPE(domain), INTENT(IN) :: grid
  2027. ! result
  2028. LOGICAL :: is_sim_start_time
  2029. TYPE(WRFU_Time) :: simulationStartTime, current_time
  2030. CALL domain_clock_get( grid, current_time=current_time, &
  2031. simulationStartTime=simulationStartTime )
  2032. is_sim_start_time = ( current_time == simulationStartTime )
  2033. END FUNCTION domain_clockissimstarttime
  2034. SUBROUTINE domain_clock_create( grid, StartTime, &
  2035. StopTime, &
  2036. TimeStep )
  2037. IMPLICIT NONE
  2038. TYPE(domain), INTENT(INOUT) :: grid
  2039. TYPE(WRFU_Time), INTENT(IN ) :: StartTime
  2040. TYPE(WRFU_Time), INTENT(IN ) :: StopTime
  2041. TYPE(WRFU_TimeInterval), INTENT(IN ) :: TimeStep
  2042. ! <DESCRIPTION>
  2043. ! This convenience routine creates the domain_clock for domain grid and
  2044. ! sets associated flags.
  2045. !
  2046. ! </DESCRIPTION>
  2047. ! Locals
  2048. INTEGER :: rc
  2049. grid%domain_clock = WRFU_ClockCreate( TimeStep= TimeStep, &
  2050. StartTime=StartTime, &
  2051. StopTime= StopTime, &
  2052. rc=rc )
  2053. IF ( rc /= WRFU_SUCCESS ) THEN
  2054. CALL wrf_error_fatal ( &
  2055. 'domain_clock_create: WRFU_ClockCreate() failed' )
  2056. ENDIF
  2057. grid%domain_clock_created = .TRUE.
  2058. RETURN
  2059. END SUBROUTINE domain_clock_create
  2060. SUBROUTINE domain_alarm_create( grid, alarm_id, interval, &
  2061. begin_time, end_time )
  2062. USE module_utility
  2063. IMPLICIT NONE
  2064. TYPE(domain), POINTER :: grid
  2065. INTEGER, INTENT(IN) :: alarm_id
  2066. TYPE(WRFU_TimeInterval), INTENT(IN), OPTIONAL :: interval
  2067. TYPE(WRFU_TimeInterval), INTENT(IN), OPTIONAL :: begin_time
  2068. TYPE(WRFU_TimeInterval), INTENT(IN), OPTIONAL :: end_time
  2069. ! <DESCRIPTION>
  2070. ! This convenience routine creates alarm alarm_id for domain grid and
  2071. ! sets associated flags.
  2072. !
  2073. ! </DESCRIPTION>
  2074. ! Locals
  2075. INTEGER :: rc
  2076. !$$$ TBH: Ideally, this could be simplified by passing all optional actual
  2077. !$$$ TBH: args into AlarmCreate. However, since operations are performed on
  2078. !$$$ TBH: the actual args in-place in the calls, they must be present for the
  2079. !$$$ TBH: operations themselves to be defined. Grrr...
  2080. LOGICAL :: interval_only, all_args, no_args
  2081. TYPE(WRFU_Time) :: startTime
  2082. interval_only = .FALSE.
  2083. all_args = .FALSE.
  2084. no_args = .FALSE.
  2085. IF ( ( .NOT. PRESENT( begin_time ) ) .AND. &
  2086. ( .NOT. PRESENT( end_time ) ) .AND. &
  2087. ( PRESENT( interval ) ) ) THEN
  2088. interval_only = .TRUE.
  2089. ELSE IF ( ( .NOT. PRESENT( begin_time ) ) .AND. &
  2090. ( .NOT. PRESENT( end_time ) ) .AND. &
  2091. ( .NOT. PRESENT( interval ) ) ) THEN
  2092. no_args = .TRUE.
  2093. ELSE IF ( ( PRESENT( begin_time ) ) .AND. &
  2094. ( PRESENT( end_time ) ) .AND. &
  2095. ( PRESENT( interval ) ) ) THEN
  2096. all_args = .TRUE.
  2097. ELSE
  2098. CALL wrf_error_fatal ( &
  2099. 'ERROR in domain_alarm_create: bad argument list' )
  2100. ENDIF
  2101. CALL domain_clock_get( grid, start_time=startTime )
  2102. IF ( interval_only ) THEN
  2103. grid%io_intervals( alarm_id ) = interval
  2104. grid%alarms( alarm_id ) = &
  2105. WRFU_AlarmCreate( clock=grid%domain_clock, &
  2106. RingInterval=interval, &
  2107. rc=rc )
  2108. ELSE IF ( no_args ) THEN
  2109. grid%alarms( alarm_id ) = &
  2110. WRFU_AlarmCreate( clock=grid%domain_clock, &
  2111. RingTime=startTime, &
  2112. rc=rc )
  2113. ELSE IF ( all_args ) THEN
  2114. grid%io_intervals( alarm_id ) = interval
  2115. grid%alarms( alarm_id ) = &
  2116. WRFU_AlarmCreate( clock=grid%domain_clock, &
  2117. RingTime=startTime + begin_time, &
  2118. RingInterval=interval, &
  2119. StopTime=startTime + end_time, &
  2120. rc=rc )
  2121. ENDIF
  2122. IF ( rc /= WRFU_SUCCESS ) THEN
  2123. CALL wrf_error_fatal ( &
  2124. 'domain_alarm_create: WRFU_AlarmCreate() failed' )
  2125. ENDIF
  2126. CALL WRFU_AlarmRingerOff( grid%alarms( alarm_id ) , rc=rc )
  2127. IF ( rc /= WRFU_SUCCESS ) THEN
  2128. CALL wrf_error_fatal ( &
  2129. 'domain_alarm_create: WRFU_AlarmRingerOff() failed' )
  2130. ENDIF
  2131. grid%alarms_created( alarm_id ) = .TRUE.
  2132. END SUBROUTINE domain_alarm_create
  2133. SUBROUTINE domain_clock_set( grid, current_timestr, &
  2134. stop_timestr, &
  2135. time_step_seconds )
  2136. IMPLICIT NONE
  2137. TYPE(domain), INTENT(INOUT) :: grid
  2138. CHARACTER (LEN=*), INTENT(IN ), OPTIONAL :: current_timestr
  2139. CHARACTER (LEN=*), INTENT(IN ), OPTIONAL :: stop_timestr
  2140. INTEGER, INTENT(IN ), OPTIONAL :: time_step_seconds
  2141. ! <DESCRIPTION>
  2142. ! This convenience routine sets clock information for domain grid.
  2143. ! The caller is responsible for ensuring that character string actual
  2144. ! arguments are big enough.
  2145. !
  2146. ! </DESCRIPTION>
  2147. ! Locals
  2148. TYPE(WRFU_Time) :: lcl_currtime, lcl_stoptime
  2149. TYPE(WRFU_TimeInterval) :: tmpTimeInterval
  2150. INTEGER :: rc
  2151. IF ( PRESENT( current_timestr ) ) THEN
  2152. CALL wrf_atotime( current_timestr(1:19), lcl_currtime )
  2153. CALL WRFU_ClockSet( grid%domain_clock, currTime=lcl_currtime, &
  2154. rc=rc )
  2155. IF ( rc /= WRFU_SUCCESS ) THEN
  2156. CALL wrf_error_fatal ( &
  2157. 'domain_clock_set: WRFU_ClockSet(CurrTime) failed' )
  2158. ENDIF
  2159. ENDIF
  2160. IF ( PRESENT( stop_timestr ) ) THEN
  2161. CALL wrf_atotime( stop_timestr(1:19), lcl_stoptime )
  2162. CALL WRFU_ClockSet( grid%domain_clock, stopTime=lcl_stoptime, &
  2163. rc=rc )
  2164. IF ( rc /= WRFU_SUCCESS ) THEN
  2165. CALL wrf_error_fatal ( &
  2166. 'domain_clock_set: WRFU_ClockSet(StopTime) failed' )
  2167. ENDIF
  2168. ENDIF
  2169. IF ( PRESENT( time_step_seconds ) ) THEN
  2170. CALL WRFU_TimeIntervalSet( tmpTimeInterval, &
  2171. S=time_step_seconds, rc=rc )
  2172. IF ( rc /= WRFU_SUCCESS ) THEN
  2173. CALL wrf_error_fatal ( &
  2174. 'domain_clock_set: WRFU_TimeIntervalSet failed' )
  2175. ENDIF
  2176. CALL WRFU_ClockSet ( grid%domain_clock, &
  2177. timeStep=tmpTimeInterval, &
  2178. rc=rc )
  2179. IF ( rc /= WRFU_SUCCESS ) THEN
  2180. CALL wrf_error_fatal ( &
  2181. 'domain_clock_set: WRFU_ClockSet(TimeStep) failed' )
  2182. ENDIF
  2183. ENDIF
  2184. RETURN
  2185. END SUBROUTINE domain_clock_set
  2186. ! Debug routine to print key clock information.
  2187. ! Printed lines include pre_str.
  2188. SUBROUTINE domain_clockprint ( level, grid, pre_str )
  2189. IMPLICIT NONE
  2190. INTEGER, INTENT( IN) :: level
  2191. TYPE(domain), INTENT( IN) :: grid
  2192. CHARACTER (LEN=*), INTENT( IN) :: pre_str
  2193. CALL wrf_clockprint ( level, grid%domain_clock, pre_str )
  2194. RETURN
  2195. END SUBROUTINE domain_clockprint
  2196. ! Advance the clock associated with grid.
  2197. ! Also updates several derived time quantities in grid state.
  2198. SUBROUTINE domain_clockadvance ( grid )
  2199. IMPLICIT NONE
  2200. TYPE(domain), INTENT(INOUT) :: grid
  2201. INTEGER :: rc
  2202. CALL domain_clockprint ( 250, grid, &
  2203. 'DEBUG domain_clockadvance(): before WRFU_ClockAdvance,' )
  2204. CALL WRFU_ClockAdvance( grid%domain_clock, rc=rc )
  2205. IF ( rc /= WRFU_SUCCESS ) THEN
  2206. CALL wrf_error_fatal ( &
  2207. 'domain_clockadvance: WRFU_ClockAdvance() failed' )
  2208. ENDIF
  2209. CALL domain_clockprint ( 250, grid, &
  2210. 'DEBUG domain_clockadvance(): after WRFU_ClockAdvance,' )
  2211. ! Update derived time quantities in grid state.
  2212. ! These are initialized in setup_timekeeping().
  2213. CALL domain_clock_get( grid, minutesSinceSimulationStart=grid%xtime )
  2214. CALL domain_clock_get( grid, currentDayOfYearReal=grid%julian )
  2215. RETURN
  2216. END SUBROUTINE domain_clockadvance
  2217. ! Set grid%gmt, grid%julday, and grid%julyr from simulation-start-date.
  2218. ! Set start_of_simulation to TRUE iff current_time == simulation_start_time
  2219. SUBROUTINE domain_setgmtetc ( grid, start_of_simulation )
  2220. IMPLICIT NONE
  2221. TYPE (domain), INTENT(INOUT) :: grid
  2222. LOGICAL, INTENT( OUT) :: start_of_simulation
  2223. ! locals
  2224. CHARACTER (LEN=132) :: message
  2225. TYPE(WRFU_Time) :: simStartTime
  2226. INTEGER :: hr, mn, sec, ms, rc
  2227. CALL domain_clockprint(150, grid, &
  2228. 'DEBUG domain_setgmtetc(): get simStartTime from clock,')
  2229. CALL domain_clock_get( grid, simulationStartTime=simStartTime, &
  2230. simulationStartTimeStr=message )
  2231. CALL WRFU_TimeGet( simStartTime, YY=grid%julyr, dayOfYear=grid%julday, &
  2232. H=hr, M=mn, S=sec, MS=ms, rc=rc)
  2233. IF ( rc /= WRFU_SUCCESS ) THEN
  2234. CALL wrf_error_fatal ( &
  2235. 'domain_setgmtetc: WRFU_TimeGet() failed' )
  2236. ENDIF
  2237. WRITE( wrf_err_message , * ) 'DEBUG domain_setgmtetc(): simulation start time = [',TRIM( message ),']'
  2238. CALL wrf_debug( 150, TRIM(wrf_err_message) )
  2239. grid%gmt=hr+real(mn)/60.+real(sec)/3600.+real(ms)/(1000*3600)
  2240. WRITE( wrf_err_message , * ) 'DEBUG domain_setgmtetc(): julyr,hr,mn,sec,ms,julday = ', &
  2241. grid%julyr,hr,mn,sec,ms,grid%julday
  2242. CALL wrf_debug( 150, TRIM(wrf_err_message) )
  2243. WRITE( wrf_err_message , * ) 'DEBUG domain_setgmtetc(): gmt = ',grid%gmt
  2244. CALL wrf_debug( 150, TRIM(wrf_err_message) )
  2245. start_of_simulation = domain_ClockIsSimStartTime(grid)
  2246. RETURN
  2247. END SUBROUTINE domain_setgmtetc
  2248. ! Set pointer to current grid.
  2249. ! To begin with, current grid is not set.
  2250. SUBROUTINE set_current_grid_ptr( grid_ptr )
  2251. IMPLICIT NONE
  2252. TYPE(domain), POINTER :: grid_ptr
  2253. !PRINT *,'DEBUG: begin set_current_grid_ptr()'
  2254. !IF ( ASSOCIATED( grid_ptr ) ) THEN
  2255. ! PRINT *,'DEBUG: set_current_grid_ptr(): current_grid is associated'
  2256. !ELSE
  2257. ! PRINT *,'DEBUG: set_current_grid_ptr(): current_grid is NOT associated'
  2258. !ENDIF
  2259. current_grid_set = .TRUE.
  2260. current_grid => grid_ptr
  2261. !PRINT *,'DEBUG: end set_current_grid_ptr()'
  2262. END SUBROUTINE set_current_grid_ptr
  2263. !******************************************************************************
  2264. ! BEGIN TEST SECTION
  2265. ! Code in the test section is used to test domain methods.
  2266. ! This code should probably be moved elsewhere, eventually.
  2267. !******************************************************************************
  2268. ! Private utility routines for domain_time_test.
  2269. SUBROUTINE domain_time_test_print ( pre_str, name_str, res_str )
  2270. IMPLICIT NONE
  2271. CHARACTER (LEN=*), INTENT(IN) :: pre_str
  2272. CHARACTER (LEN=*), INTENT(IN) :: name_str
  2273. CHARACTER (LEN=*), INTENT(IN) :: res_str
  2274. CHARACTER (LEN=512) :: out_str
  2275. WRITE (out_str, &
  2276. FMT="('DOMAIN_TIME_TEST ',A,': ',A,' = ',A)") &
  2277. TRIM(pre_str), TRIM(name_str), TRIM(res_str)
  2278. CALL wrf_debug( 0, TRIM(out_str) )
  2279. END SUBROUTINE domain_time_test_print
  2280. ! Test adjust_io_timestr
  2281. SUBROUTINE test_adjust_io_timestr( TI_h, TI_m, TI_s, &
  2282. CT_yy, CT_mm, CT_dd, CT_h, CT_m, CT_s, &
  2283. ST_yy, ST_mm, ST_dd, ST_h, ST_m, ST_s, &
  2284. res_str, testname )
  2285. INTEGER, INTENT(IN) :: TI_H
  2286. INTEGER, INTENT(IN) :: TI_M
  2287. INTEGER, INTENT(IN) :: TI_S
  2288. INTEGER, INTENT(IN) :: CT_YY
  2289. INTEGER, INTENT(IN) :: CT_MM ! month
  2290. INTEGER, INTENT(IN) :: CT_DD ! day of month
  2291. INTEGER, INTENT(IN) :: CT_H
  2292. INTEGER, INTENT(IN) :: CT_M
  2293. INTEGER, INTENT(IN) :: CT_S
  2294. INTEGER, INTENT(IN) :: ST_YY
  2295. INTEGER, INTENT(IN) :: ST_MM ! month
  2296. INTEGER, INTENT(IN) :: ST_DD ! day of month
  2297. INTEGER, INTENT(IN) :: ST_H
  2298. INTEGER, INTENT(IN) :: ST_M
  2299. INTEGER, INTENT(IN) :: ST_S
  2300. CHARACTER (LEN=*), INTENT(IN) :: res_str
  2301. CHARACTER (LEN=*), INTENT(IN) :: testname
  2302. ! locals
  2303. TYPE(WRFU_TimeInterval) :: TI
  2304. TYPE(WRFU_Time) :: CT, ST
  2305. LOGICAL :: test_passed
  2306. INTEGER :: rc
  2307. CHARACTER(LEN=WRFU_MAXSTR) :: TI_str, CT_str, ST_str, computed_str
  2308. ! TI
  2309. CALL WRFU_TimeIntervalSet( TI, H=TI_H, M=TI_M, S=TI_S, rc=rc )
  2310. CALL wrf_check_error( WRFU_SUCCESS, rc, &
  2311. 'FAIL: '//TRIM(testname)//'WRFU_TimeIntervalSet() ', &
  2312. __FILE__ , &
  2313. __LINE__ )
  2314. CALL WRFU_TimeIntervalGet( TI, timeString=TI_str, rc=rc )
  2315. CALL wrf_check_error( WRFU_SUCCESS, rc, &
  2316. 'FAIL: '//TRIM(testname)//'WRFU_TimeGet() ', &
  2317. __FILE__ , &
  2318. __LINE__ )
  2319. ! CT
  2320. CALL WRFU_TimeSet( CT, YY=CT_YY, MM=CT_MM, DD=CT_DD , &
  2321. H=CT_H, M=CT_M, S=CT_S, rc=rc )
  2322. CALL wrf_check_error( WRFU_SUCCESS, rc, &
  2323. 'FAIL: '//TRIM(testname)//'WRFU_TimeSet() ', &
  2324. __FILE__ , &
  2325. __LINE__ )
  2326. CALL WRFU_TimeGet( CT, timeString=CT_str, rc=rc )
  2327. CALL wrf_check_error( WRFU_SUCCESS, rc, &
  2328. 'FAIL: '//TRIM(testname)//'WRFU_TimeGet() ', &
  2329. __FILE__ , &
  2330. __LINE__ )
  2331. ! ST
  2332. CALL WRFU_TimeSet( ST, YY=ST_YY, MM=ST_MM, DD=ST_DD , &
  2333. H=ST_H, M=ST_M, S=ST_S, rc=rc )
  2334. CALL wrf_check_error( WRFU_SUCCESS, rc, &
  2335. 'FAIL: '//TRIM(testname)//'WRFU_TimeSet() ', &
  2336. __FILE__ , &
  2337. __LINE__ )
  2338. CALL WRFU_TimeGet( ST, timeString=ST_str, rc=rc )
  2339. CALL wrf_check_error( WRFU_SUCCESS, rc, &
  2340. 'FAIL: '//TRIM(testname)//'WRFU_TimeGet() ', &
  2341. __FILE__ , &
  2342. __LINE__ )
  2343. ! Test
  2344. CALL adjust_io_timestr ( TI, CT, ST, computed_str )
  2345. ! check result
  2346. test_passed = .FALSE.
  2347. IF ( LEN_TRIM(res_str) == LEN_TRIM(computed_str) ) THEN
  2348. IF ( res_str(1:LEN_TRIM(res_str)) == computed_str(1:LEN_TRIM(computed_str)) ) THEN
  2349. test_passed = .TRUE.
  2350. ENDIF
  2351. ENDIF
  2352. ! print result
  2353. IF ( test_passed ) THEN
  2354. WRITE(*,FMT='(A)') 'PASS: '//TRIM(testname)
  2355. ELSE
  2356. WRITE(*,*) 'FAIL: ',TRIM(testname),': adjust_io_timestr(', &
  2357. TRIM(TI_str),',',TRIM(CT_str),',',TRIM(ST_str),') expected <', &
  2358. TRIM(res_str),'> but computed <',TRIM(computed_str),'>'
  2359. ENDIF
  2360. END SUBROUTINE test_adjust_io_timestr
  2361. ! Print lots of time-related information for testing and debugging.
  2362. ! Printed lines include pre_str and special string DOMAIN_TIME_TEST
  2363. ! suitable for grepping by test scripts.
  2364. ! Returns immediately unless self_test_domain has been set to .true. in
  2365. ! namelist /time_control/ .
  2366. SUBROUTINE domain_time_test ( grid, pre_str )
  2367. IMPLICIT NONE
  2368. TYPE(domain), INTENT(IN) :: grid
  2369. CHARACTER (LEN=*), INTENT(IN) :: pre_str
  2370. ! locals
  2371. LOGICAL, SAVE :: one_time_tests_done = .FALSE.
  2372. REAL :: minutesSinceSimulationStart
  2373. INTEGER :: advance_count, rc
  2374. REAL :: currentDayOfYearReal
  2375. TYPE(WRFU_TimeInterval) :: timeSinceSimulationStart
  2376. TYPE(WRFU_Time) :: simulationStartTime
  2377. CHARACTER (LEN=512) :: res_str
  2378. LOGICAL :: self_test_domain
  2379. !
  2380. ! NOTE: test_adjust_io_timestr() (see below) is a self-test that
  2381. ! prints PASS/FAIL/ERROR messages in a standard format. All
  2382. ! of the other tests should be strucutred the same way,
  2383. ! someday.
  2384. !
  2385. CALL nl_get_self_test_domain( 1, self_test_domain )
  2386. IF ( self_test_domain ) THEN
  2387. CALL domain_clock_get( grid, advanceCount=advance_count )
  2388. WRITE ( res_str, FMT="(I8.8)" ) advance_count
  2389. CALL domain_time_test_print( pre_str, 'advanceCount', res_str )
  2390. CALL domain_clock_get( grid, currentDayOfYearReal=currentDayOfYearReal )
  2391. WRITE ( res_str, FMT='(F10.6)' ) currentDayOfYearReal
  2392. CALL domain_time_test_print( pre_str, 'currentDayOfYearReal', res_str )
  2393. CALL domain_clock_get( grid, minutesSinceSimulationStart=minutesSinceSimulationStart )
  2394. WRITE ( res_str, FMT='(F10.6)' ) minutesSinceSimulationStart
  2395. CALL domain_time_test_print( pre_str, 'minutesSinceSimulationStart', res_str )
  2396. CALL domain_clock_get( grid, current_timestr=res_str )
  2397. CALL domain_time_test_print( pre_str, 'current_timestr', res_str )
  2398. CALL domain_clock_get( grid, current_timestr_frac=res_str )
  2399. CALL domain_time_test_print( pre_str, 'current_timestr_frac', res_str )
  2400. CALL domain_clock_get( grid, timeSinceSimulationStart=timeSinceSimulationStart )
  2401. CALL WRFU_TimeIntervalGet( timeSinceSimulationStart, timeString=res_str, rc=rc )
  2402. IF ( rc /= WRFU_SUCCESS ) THEN
  2403. CALL wrf_error_fatal ( &
  2404. 'domain_time_test: WRFU_TimeIntervalGet() failed' )
  2405. ENDIF
  2406. CALL domain_time_test_print( pre_str, 'timeSinceSimulationStart', res_str )
  2407. ! The following tests should only be done once, the first time this
  2408. ! routine is called.
  2409. IF ( .NOT. one_time_tests_done ) THEN
  2410. one_time_tests_done = .TRUE.
  2411. CALL domain_clock_get( grid, simulationStartTimeStr=res_str )
  2412. CALL domain_time_test_print( pre_str, 'simulationStartTime', res_str )
  2413. CALL domain_clock_get( grid, start_timestr=res_str )
  2414. CALL domain_time_test_print( pre_str, 'start_timestr', res_str )
  2415. CALL domain_clock_get( grid, stop_timestr=res_str )
  2416. CALL domain_time_test_print( pre_str, 'stop_timestr', res_str )
  2417. CALL domain_clock_get( grid, time_stepstr=res_str )
  2418. CALL domain_time_test_print( pre_str, 'time_stepstr', res_str )
  2419. CALL domain_clock_get( grid, time_stepstr_frac=res_str )
  2420. CALL domain_time_test_print( pre_str, 'time_stepstr_frac', res_str )
  2421. ! Test adjust_io_timestr()
  2422. ! CT = 2000-01-26_00:00:00 (current time)
  2423. ! ST = 2000-01-24_12:00:00 (start time)
  2424. ! TI = 00000_03:00:00 (time interval)
  2425. ! the resulting time string should be:
  2426. ! 2000-01-26_00:00:00
  2427. CALL test_adjust_io_timestr( TI_h=3, TI_m=0, TI_s=0, &
  2428. CT_yy=2000, CT_mm=1, CT_dd=26, CT_h=0, CT_m=0, CT_s=0, &
  2429. ST_yy=2000, ST_mm=1, ST_dd=24, ST_h=12, ST_m=0, ST_s=0, &
  2430. res_str='2000-01-26_00:00:00', testname='adjust_io_timestr_1' )
  2431. ! this should fail (and does)
  2432. ! CALL test_adjust_io_timestr( TI_h=3, TI_m=0, TI_s=0, &
  2433. ! CT_yy=2000, CT_mm=1, CT_dd=26, CT_h=0, CT_m=0, CT_s=0, &
  2434. ! ST_yy=2000, ST_mm=1, ST_dd=24, ST_h=12, ST_m=0, ST_s=0, &
  2435. ! res_str='2000-01-26_00:00:01', testname='adjust_io_timestr_FAIL1' )
  2436. ENDIF
  2437. ENDIF
  2438. RETURN
  2439. END SUBROUTINE domain_time_test
  2440. !******************************************************************************
  2441. ! END TEST SECTION
  2442. !******************************************************************************
  2443. END MODULE module_domain
  2444. ! The following routines are outside this module to avoid build dependences.
  2445. ! Get current time as a string (current time from clock attached to the
  2446. ! current_grid). Includes fractional part, if present.
  2447. ! Returns empty string if current_grid is not set or if timing has not yet
  2448. ! been set up on current_grid.
  2449. SUBROUTINE get_current_time_string( time_str )
  2450. USE module_domain
  2451. IMPLICIT NONE
  2452. CHARACTER (LEN=*), INTENT(OUT) :: time_str
  2453. ! locals
  2454. INTEGER :: debug_level_lcl
  2455. !PRINT *,'DEBUG: begin get_current_time_string()'
  2456. time_str = ''
  2457. IF ( current_grid_set ) THEN
  2458. !$$$DEBUG
  2459. !PRINT *,'DEBUG: get_current_time_string(): checking association of current_grid...'
  2460. !IF ( ASSOCIATED( current_grid ) ) THEN
  2461. ! PRINT *,'DEBUG: get_current_time_string(): current_grid is associated'
  2462. !ELSE
  2463. ! PRINT *,'DEBUG: get_current_time_string(): current_grid is NOT associated'
  2464. !ENDIF
  2465. !$$$END DEBUG
  2466. IF ( current_grid%time_set ) THEN
  2467. !PRINT *,'DEBUG: get_current_time_string(): calling domain_clock_get()'
  2468. ! set debug_level to zero and clear current_grid_set to avoid recursion
  2469. CALL get_wrf_debug_level( debug_level_lcl )
  2470. CALL set_wrf_debug_level ( 0 )
  2471. current_grid_set = .FALSE.
  2472. CALL domain_clock_get( current_grid, current_timestr_frac=time_str )
  2473. ! restore debug_level and current_grid_set
  2474. CALL set_wrf_debug_level ( debug_level_lcl )
  2475. current_grid_set = .TRUE.
  2476. !PRINT *,'DEBUG: get_current_time_string(): back from domain_clock_get()'
  2477. ENDIF
  2478. ENDIF
  2479. !PRINT *,'DEBUG: end get_current_time_string()'
  2480. END SUBROUTINE get_current_time_string
  2481. ! Get current domain name as a string of form "d<NN>" where "<NN>" is
  2482. ! grid%id printed in two characters, with leading zero if needed ("d01",
  2483. ! "d02", etc.).
  2484. ! Return empty string if current_grid not set.
  2485. SUBROUTINE get_current_grid_name( grid_str )
  2486. USE module_domain
  2487. IMPLICIT NONE
  2488. CHARACTER (LEN=*), INTENT(OUT) :: grid_str
  2489. grid_str = ''
  2490. IF ( current_grid_set ) THEN
  2491. WRITE(grid_str,FMT="('d',I2.2)") current_grid%id
  2492. ENDIF
  2493. END SUBROUTINE get_current_grid_name
  2494. ! moved these outside module domain to avoid circular reference from module_alloc_space which also uses
  2495. SUBROUTINE get_ijk_from_grid_ext ( grid , &
  2496. ids, ide, jds, jde, kds, kde, &
  2497. ims, ime, jms, jme, kms, kme, &
  2498. ips, ipe, jps, jpe, kps, kpe, &
  2499. imsx, imex, jmsx, jmex, kmsx, kmex, &
  2500. ipsx, ipex, jpsx, jpex, kpsx, kpex, &
  2501. imsy, imey, jmsy, jmey, kmsy, kmey, &
  2502. ipsy, ipey, jpsy, jpey, kpsy, kpey )
  2503. USE module_domain
  2504. IMPLICIT NONE
  2505. TYPE( domain ), INTENT (IN) :: grid
  2506. INTEGER, INTENT(OUT) :: &
  2507. ids, ide, jds, jde, kds, kde, &
  2508. ims, ime, jms, jme, kms, kme, &
  2509. ips, ipe, jps, jpe, kps, kpe, &
  2510. imsx, imex, jmsx, jmex, kmsx, kmex, &
  2511. ipsx, ipex, jpsx, jpex, kpsx, kpex, &
  2512. imsy, imey, jmsy, jmey, kmsy, kmey, &
  2513. ipsy, ipey, jpsy, jpey, kpsy, kpey
  2514. CALL get_ijk_from_grid2 ( grid , &
  2515. ids, ide, jds, jde, kds, kde, &
  2516. ims, ime, jms, jme, kms, kme, &
  2517. ips, ipe, jps, jpe, kps, kpe )
  2518. data_ordering : SELECT CASE ( model_data_order )
  2519. CASE ( DATA_ORDER_XYZ )
  2520. imsx = grid%sm31x ; imex = grid%em31x ; jmsx = grid%sm32x ; jmex = grid%em32x ; kmsx = grid%sm33x ; kmex = grid%em33x ;
  2521. ipsx = grid%sp31x ; ipex = grid%ep31x ; jpsx = grid%sp32x ; jpex = grid%ep32x ; kpsx = grid%sp33x ; kpex = grid%ep33x ;
  2522. imsy = grid%sm31y ; imey = grid%em31y ; jmsy = grid%sm32y ; jmey = grid%em32y ; kmsy = grid%sm33y ; kmey = grid%em33y ;
  2523. ipsy = grid%sp31y ; ipey = grid%ep31y ; jpsy = grid%sp32y ; jpey = grid%ep32y ; kpsy = grid%sp33y ; kpey = grid%ep33y ;
  2524. CASE ( DATA_ORDER_YXZ )
  2525. imsx = grid%sm32x ; imex = grid%em32x ; jmsx = grid%sm31x ; jmex = grid%em31x ; kmsx = grid%sm33x ; kmex = grid%em33x ;
  2526. ipsx = grid%sp32x ; ipex = grid%ep32x ; jpsx = grid%sp31x ; jpex = grid%ep31x ; kpsx = grid%sp33x ; kpex = grid%ep33x ;
  2527. imsy = grid%sm32y ; imey = grid%em32y ; jmsy = grid%sm31y ; jmey = grid%em31y ; kmsy = grid%sm33y ; kmey = grid%em33y ;
  2528. ipsy = grid%sp32y ; ipey = grid%ep32y ; jpsy = grid%sp31y ; jpey = grid%ep31y ; kpsy = grid%sp33y ; kpey = grid%ep33y ;
  2529. CASE ( DATA_ORDER_ZXY )
  2530. imsx = grid%sm32x ; imex = grid%em32x ; jmsx = grid%sm33x ; jmex = grid%em33x ; kmsx = grid%sm31x ; kmex = grid%em31x ;
  2531. ipsx = grid%sp32x ; ipex = grid%ep32x ; jpsx = grid%sp33x ; jpex = grid%ep33x ; kpsx = grid%sp31x ; kpex = grid%ep31x ;
  2532. imsy = grid%sm32y ; imey = grid%em32y ; jmsy = grid%sm33y ; jmey = grid%em33y ; kmsy = grid%sm31y ; kmey = grid%em31y ;
  2533. ipsy = grid%sp32y ; ipey = grid%ep32y ; jpsy = grid%sp33y ; jpey = grid%ep33y ; kpsy = grid%sp31y ; kpey = grid%ep31y ;
  2534. CASE ( DATA_ORDER_ZYX )
  2535. imsx = grid%sm33x ; imex = grid%em33x ; jmsx = grid%sm32x ; jmex = grid%em32x ; kmsx = grid%sm31x ; kmex = grid%em31x ;
  2536. ipsx = grid%sp33x ; ipex = grid%ep33x ; jpsx = grid%sp32x ; jpex = grid%ep32x ; kpsx = grid%sp31x ; kpex = grid%ep31x ;
  2537. imsy = grid%sm33y ; imey = grid%em33y ; jmsy = grid%sm32y ; jmey = grid%em32y ; kmsy = grid%sm31y ; kmey = grid%em31y ;
  2538. ipsy = grid%sp33y ; ipey = grid%ep33y ; jpsy = grid%sp32y ; jpey = grid%ep32y ; kpsy = grid%sp31y ; kpey = grid%ep31y ;
  2539. CASE ( DATA_ORDER_XZY )
  2540. imsx = grid%sm31x ; imex = grid%em31x ; jmsx = grid%sm33x ; jmex = grid%em33x ; kmsx = grid%sm32x ; kmex = grid%em32x ;
  2541. ipsx = grid%sp31x ; ipex = grid%ep31x ; jpsx = grid%sp33x ; jpex = grid%ep33x ; kpsx = grid%sp32x ; kpex = grid%ep32x ;
  2542. imsy = grid%sm31y ; imey = grid%em31y ; jmsy = grid%sm33y ; jmey = grid%em33y ; kmsy = grid%sm32y ; kmey = grid%em32y ;
  2543. ipsy = grid%sp31y ; ipey = grid%ep31y ; jpsy = grid%sp33y ; jpey = grid%ep33y ; kpsy = grid%sp32y ; kpey = grid%ep32y ;
  2544. CASE ( DATA_ORDER_YZX )
  2545. imsx = grid%sm33x ; imex = grid%em33x ; jmsx = grid%sm31x ; jmex = grid%em31x ; kmsx = grid%sm32x ; kmex = grid%em32x ;
  2546. ipsx = grid%sp33x ; ipex = grid%ep33x ; jpsx = grid%sp31x ; jpex = grid%ep31x ; kpsx = grid%sp32x ; kpex = grid%ep32x ;
  2547. imsy = grid%sm33y ; imey = grid%em33y ; jmsy = grid%sm31y ; jmey = grid%em31y ; kmsy = grid%sm32y ; kmey = grid%em32y ;
  2548. ipsy = grid%sp33y ; ipey = grid%ep33y ; jpsy = grid%sp31y ; jpey = grid%ep31y ; kpsy = grid%sp32y ; kpey = grid%ep32y ;
  2549. END SELECT data_ordering
  2550. END SUBROUTINE get_ijk_from_grid_ext
  2551. ! return the values for subgrid whose refinement is in grid%sr
  2552. ! note when using this routine, it does not affect K. For K
  2553. ! (vertical), it just returns what get_ijk_from_grid does
  2554. SUBROUTINE get_ijk_from_subgrid_ext ( grid , &
  2555. ids0, ide0, jds0, jde0, kds0, kde0, &
  2556. ims0, ime0, jms0, jme0, kms0, kme0, &
  2557. ips0, ipe0, jps0, jpe0, kps0, kpe0 )
  2558. USE module_domain
  2559. IMPLICIT NONE
  2560. TYPE( domain ), INTENT (IN) :: grid
  2561. INTEGER, INTENT(OUT) :: &
  2562. ids0, ide0, jds0, jde0, kds0, kde0, &
  2563. ims0, ime0, jms0, jme0, kms0, kme0, &
  2564. ips0, ipe0, jps0, jpe0, kps0, kpe0
  2565. ! Local
  2566. INTEGER :: &
  2567. ids, ide, jds, jde, kds, kde, &
  2568. ims, ime, jms, jme, kms, kme, &
  2569. ips, ipe, jps, jpe, kps, kpe
  2570. CALL get_ijk_from_grid ( grid , &
  2571. ids, ide, jds, jde, kds, kde, &
  2572. ims, ime, jms, jme, kms, kme, &
  2573. ips, ipe, jps, jpe, kps, kpe )
  2574. ids0 = ids
  2575. ide0 = ide * grid%sr_x
  2576. ims0 = (ims-1)*grid%sr_x+1
  2577. ime0 = ime * grid%sr_x
  2578. ips0 = (ips-1)*grid%sr_x+1
  2579. ipe0 = ipe * grid%sr_x
  2580. jds0 = jds
  2581. jde0 = jde * grid%sr_y
  2582. jms0 = (jms-1)*grid%sr_y+1
  2583. jme0 = jme * grid%sr_y
  2584. jps0 = (jps-1)*grid%sr_y+1
  2585. jpe0 = jpe * grid%sr_y
  2586. kds0 = kds
  2587. kde0 = kde
  2588. kms0 = kms
  2589. kme0 = kme
  2590. kps0 = kps
  2591. kpe0 = kpe
  2592. RETURN
  2593. END SUBROUTINE get_ijk_from_subgrid_ext
  2594. ! find the grid based on the id reference and return that
  2595. SUBROUTINE get_dims_from_grid_id ( id &
  2596. ,ds, de &
  2597. ,ms, me &
  2598. ,ps, pe &
  2599. ,mxs, mxe &
  2600. ,pxs, pxe &
  2601. ,mys, mye &
  2602. ,pys, pye )
  2603. USE module_domain, ONLY : domain, head_grid, find_grid_by_id
  2604. IMPLICIT NONE
  2605. TYPE( domain ), POINTER :: grid
  2606. INTEGER, INTENT(IN ) :: id
  2607. INTEGER, DIMENSION(3), INTENT(INOUT) :: &
  2608. ds, de &
  2609. ,ms, me &
  2610. ,ps, pe &
  2611. ,mxs, mxe &
  2612. ,pxs, pxe &
  2613. ,mys, mye &
  2614. ,pys, pye
  2615. !local
  2616. CHARACTER*256 mess
  2617. NULLIFY( grid )
  2618. CALL find_grid_by_id ( id, head_grid, grid )
  2619. IF ( ASSOCIATED(grid) ) THEN
  2620. ds(1) = grid%sd31 ; de(1) = grid%ed31 ; ds(2) = grid%sd32 ; de(2) = grid%ed32 ; ds(3) = grid%sd33 ; de(3) = grid%ed33 ;
  2621. ms(1) = grid%sm31 ; me(1) = grid%em31 ; ms(2) = grid%sm32 ; me(2) = grid%em32 ; ms(3) = grid%sm33 ; me(3) = grid%em33 ;
  2622. ps(1) = grid%sp31 ; pe(1) = grid%ep31 ; ps(2) = grid%sp32 ; pe(2) = grid%ep32 ; ps(3) = grid%sp33 ; pe(3) = grid%ep33 ;
  2623. mxs(1) = grid%sm31x ; mxe(1) = grid%em31x
  2624. mxs(2) = grid%sm32x ; mxe(2) = grid%em32x
  2625. mxs(3) = grid%sm33x ; mxe(3) = grid%em33x
  2626. pxs(1) = grid%sp31x ; pxe(1) = grid%ep31x
  2627. pxs(2) = grid%sp32x ; pxe(2) = grid%ep32x
  2628. pxs(3) = grid%sp33x ; pxe(3) = grid%ep33x
  2629. mys(1) = grid%sm31y ; mye(1) = grid%em31y
  2630. mys(2) = grid%sm32y ; mye(2) = grid%em32y
  2631. mys(3) = grid%sm33y ; mye(3) = grid%em33y
  2632. pys(1) = grid%sp31y ; pye(1) = grid%ep31y
  2633. pys(2) = grid%sp32y ; pye(2) = grid%ep32y
  2634. pys(3) = grid%sp33y ; pye(3) = grid%ep33y
  2635. ELSE
  2636. WRITE(mess,*)'internal error: get_ijk_from_grid_id: no such grid id:',id
  2637. CALL wrf_error_fatal(TRIM(mess))
  2638. ENDIF
  2639. END SUBROUTINE get_dims_from_grid_id
  2640. ! find the grid based on the id reference and return that
  2641. SUBROUTINE get_ijk_from_grid_id ( id , &
  2642. ids, ide, jds, jde, kds, kde, &
  2643. ims, ime, jms, jme, kms, kme, &
  2644. ips, ipe, jps, jpe, kps, kpe, &
  2645. imsx, imex, jmsx, jmex, kmsx, kmex, &
  2646. ipsx, ipex, jpsx, jpex, kpsx, kpex, &
  2647. imsy, imey, jmsy, jmey, kmsy, kmey, &
  2648. ipsy, ipey, jpsy, jpey, kpsy, kpey )
  2649. USE module_domain, ONLY : domain, head_grid, find_grid_by_id, get_ijk_from_grid
  2650. IMPLICIT NONE
  2651. TYPE( domain ), POINTER :: grid
  2652. INTEGER, INTENT(IN ) :: id
  2653. INTEGER, INTENT(OUT) :: &
  2654. ids, ide, jds, jde, kds, kde, &
  2655. ims, ime, jms, jme, kms, kme, &
  2656. ips, ipe, jps, jpe, kps, kpe, &
  2657. imsx, imex, jmsx, jmex, kmsx, kmex, &
  2658. ipsx, ipex, jpsx, jpex, kpsx, kpex, &
  2659. imsy, imey, jmsy, jmey, kmsy, kmey, &
  2660. ipsy, ipey, jpsy, jpey, kpsy, kpey
  2661. !local
  2662. CHARACTER*256 mess
  2663. NULLIFY( grid )
  2664. CALL find_grid_by_id ( id, head_grid, grid )
  2665. IF ( ASSOCIATED(grid) ) THEN
  2666. CALL get_ijk_from_grid ( grid , &
  2667. ids, ide, jds, jde, kds, kde, &
  2668. ims, ime, jms, jme, kms, kme, &
  2669. ips, ipe, jps, jpe, kps, kpe, &
  2670. imsx, imex, jmsx, jmex, kmsx, kmex, &
  2671. ipsx, ipex, jpsx, jpex, kpsx, kpex, &
  2672. imsy, imey, jmsy, jmey, kmsy, kmey, &
  2673. ipsy, ipey, jpsy, jpey, kpsy, kpey )
  2674. ELSE
  2675. WRITE(mess,*)'internal error: get_ijk_from_grid_id: no such grid id:',id
  2676. CALL wrf_error_fatal(TRIM(mess))
  2677. ENDIF
  2678. END SUBROUTINE get_ijk_from_grid_id
  2679. ! version of this routine that can be called from set_scalar_indices_from_config in
  2680. ! module_configure, which can not USE module_domain without creating a circular use assocaition
  2681. SUBROUTINE modify_io_masks ( id )
  2682. USE module_domain, ONLY : domain, modify_io_masks1, head_grid, find_grid_by_id
  2683. IMPLICIT NONE
  2684. INTEGER, INTENT(IN) :: id
  2685. TYPE(domain), POINTER :: grid
  2686. !write(0,*)'modify_io_masks head_grid ',id,ASSOCIATED(head_grid)
  2687. CALL find_grid_by_id( id, head_grid, grid )
  2688. !write(0,*)'modify_io_masks grid ',id,ASSOCIATED(grid)
  2689. IF ( ASSOCIATED( grid ) ) CALL modify_io_masks1( grid, id )
  2690. RETURN
  2691. END SUBROUTINE modify_io_masks