PageRenderTime 79ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 2ms

/wrfv2_fire/external/RSL_LITE/module_dm.F

http://github.com/jbeezley/wrf-fire
FORTRAN Legacy | 4562 lines | 3088 code | 503 blank | 971 comment | 19 complexity | f5d2014a5e852efe6c1288f8887dbdf5 MD5 | raw file
Possible License(s): AGPL-1.0
  1. !WRF:PACKAGE:RSL
  2. !
  3. MODULE module_dm
  4. USE module_machine
  5. USE module_wrf_error
  6. USE module_driver_constants
  7. ! USE module_comm_dm
  8. IMPLICIT NONE
  9. #if ( NMM_CORE == 1 ) || defined( WRF_CHEM )
  10. INTEGER, PARAMETER :: max_halo_width = 6
  11. #else
  12. INTEGER, PARAMETER :: max_halo_width = 6 ! 5
  13. #endif
  14. INTEGER :: ips_save, ipe_save, jps_save, jpe_save, itrace
  15. INTEGER ntasks, ntasks_y, ntasks_x, mytask, mytask_x, mytask_y
  16. INTEGER local_communicator, local_communicator_periodic, local_iocommunicator
  17. INTEGER local_communicator_x, local_communicator_y ! subcommunicators for rows and cols of mesh
  18. LOGICAL :: dm_debug_flag = .FALSE.
  19. INTERFACE wrf_dm_maxval
  20. #if ( defined(PROMOTE_FLOAT) || ( RWORDSIZE == DWORDSIZE ) )
  21. MODULE PROCEDURE wrf_dm_maxval_real , wrf_dm_maxval_integer
  22. #else
  23. MODULE PROCEDURE wrf_dm_maxval_real , wrf_dm_maxval_integer, wrf_dm_maxval_doubleprecision
  24. #endif
  25. END INTERFACE
  26. INTERFACE wrf_dm_minval ! gopal's doing
  27. #if ( defined(PROMOTE_FLOAT) || ( RWORDSIZE == DWORDSIZE ) )
  28. MODULE PROCEDURE wrf_dm_minval_real , wrf_dm_minval_integer
  29. #else
  30. MODULE PROCEDURE wrf_dm_minval_real , wrf_dm_minval_integer, wrf_dm_minval_doubleprecision
  31. #endif
  32. END INTERFACE
  33. CONTAINS
  34. SUBROUTINE MPASPECT( P, MINM, MINN, PROCMIN_M, PROCMIN_N )
  35. IMPLICIT NONE
  36. INTEGER P, M, N, MINI, MINM, MINN, PROCMIN_M, PROCMIN_N
  37. MINI = 2*P
  38. MINM = 1
  39. MINN = P
  40. DO M = 1, P
  41. IF ( MOD( P, M ) .EQ. 0 ) THEN
  42. N = P / M
  43. IF ( ABS(M-N) .LT. MINI &
  44. .AND. M .GE. PROCMIN_M &
  45. .AND. N .GE. PROCMIN_N &
  46. ) THEN
  47. MINI = ABS(M-N)
  48. MINM = M
  49. MINN = N
  50. ENDIF
  51. ENDIF
  52. ENDDO
  53. IF ( MINM .LT. PROCMIN_M .OR. MINN .LT. PROCMIN_N ) THEN
  54. WRITE( wrf_err_message , * )'MPASPECT: UNABLE TO GENERATE PROCESSOR MESH. STOPPING.'
  55. CALL wrf_message ( TRIM ( wrf_err_message ) )
  56. WRITE(0,*)' PROCMIN_M ', PROCMIN_M
  57. WRITE( wrf_err_message , * )' PROCMIN_M ', PROCMIN_M
  58. CALL wrf_message ( TRIM ( wrf_err_message ) )
  59. WRITE( wrf_err_message , * )' PROCMIN_N ', PROCMIN_N
  60. CALL wrf_message ( TRIM ( wrf_err_message ) )
  61. WRITE( wrf_err_message , * )' P ', P
  62. CALL wrf_message ( TRIM ( wrf_err_message ) )
  63. WRITE( wrf_err_message , * )' MINM ', MINM
  64. CALL wrf_message ( TRIM ( wrf_err_message ) )
  65. WRITE( wrf_err_message , * )' MINN ', MINN
  66. CALL wrf_message ( TRIM ( wrf_err_message ) )
  67. CALL wrf_error_fatal ( 'module_dm: mpaspect' )
  68. ENDIF
  69. RETURN
  70. END SUBROUTINE MPASPECT
  71. SUBROUTINE compute_mesh( ntasks , ntasks_x, ntasks_y )
  72. IMPLICIT NONE
  73. INTEGER, INTENT(IN) :: ntasks
  74. INTEGER, INTENT(OUT) :: ntasks_x, ntasks_y
  75. CALL nl_get_nproc_x ( 1, ntasks_x )
  76. CALL nl_get_nproc_y ( 1, ntasks_y )
  77. ! check if user has specified in the namelist
  78. IF ( ntasks_x .GT. 0 .OR. ntasks_y .GT. 0 ) THEN
  79. ! if only ntasks_x is specified then make it 1-d decomp in i
  80. IF ( ntasks_x .GT. 0 .AND. ntasks_y .EQ. -1 ) THEN
  81. ntasks_y = ntasks / ntasks_x
  82. ! if only ntasks_y is specified then make it 1-d decomp in j
  83. ELSE IF ( ntasks_x .EQ. -1 .AND. ntasks_y .GT. 0 ) THEN
  84. ntasks_x = ntasks / ntasks_y
  85. ENDIF
  86. ! make sure user knows what they're doing
  87. IF ( ntasks_x * ntasks_y .NE. ntasks ) THEN
  88. WRITE( wrf_err_message , * )'WRF_DM_INITIALIZE (RSL_LITE): nproc_x * nproc_y in namelist ne ',ntasks
  89. CALL wrf_error_fatal ( wrf_err_message )
  90. ENDIF
  91. ELSE
  92. ! When neither is specified, work out mesh with MPASPECT
  93. ! Pass nproc_ln and nproc_nt so that number of procs in
  94. ! i-dim (nproc_ln) is equal or lesser.
  95. CALL mpaspect ( ntasks, ntasks_x, ntasks_y, 1, 1 )
  96. ENDIF
  97. END SUBROUTINE compute_mesh
  98. SUBROUTINE wrf_dm_initialize
  99. IMPLICIT NONE
  100. #ifndef STUBMPI
  101. INCLUDE 'mpif.h'
  102. INTEGER :: local_comm, local_comm2, new_local_comm, group, newgroup, p, p1, ierr
  103. INTEGER, ALLOCATABLE, DIMENSION(:) :: ranks
  104. INTEGER comdup
  105. INTEGER, DIMENSION(2) :: dims, coords
  106. LOGICAL, DIMENSION(2) :: isperiodic
  107. LOGICAL :: reorder_mesh
  108. CALL wrf_get_dm_communicator ( local_comm )
  109. CALL mpi_comm_size( local_comm, ntasks, ierr )
  110. CALL nl_get_reorder_mesh( 1, reorder_mesh )
  111. CALL compute_mesh( ntasks, ntasks_x, ntasks_y )
  112. WRITE( wrf_err_message , * )'Ntasks in X ',ntasks_x,', ntasks in Y ',ntasks_y
  113. CALL wrf_message( wrf_err_message )
  114. CALL mpi_comm_rank( local_comm, mytask, ierr )
  115. ! extra code to reorder the communicator 20051212jm
  116. IF ( reorder_mesh ) THEN
  117. ALLOCATE (ranks(ntasks))
  118. CALL mpi_comm_dup ( local_comm , local_comm2, ierr )
  119. CALL mpi_comm_group ( local_comm2, group, ierr )
  120. DO p1=1,ntasks
  121. p = p1 - 1
  122. ranks(p1) = mod( p , ntasks_x ) * ntasks_y + p / ntasks_x
  123. ENDDO
  124. CALL mpi_group_incl( group, ntasks, ranks, newgroup, ierr )
  125. DEALLOCATE (ranks)
  126. CALL mpi_comm_create( local_comm2, newgroup, new_local_comm , ierr )
  127. ELSE
  128. new_local_comm = local_comm
  129. ENDIF
  130. ! end extra code to reorder the communicator 20051212jm
  131. dims(1) = ntasks_y ! rows
  132. dims(2) = ntasks_x ! columns
  133. isperiodic(1) = .false.
  134. isperiodic(2) = .false.
  135. CALL mpi_cart_create( new_local_comm, 2, dims, isperiodic, .false., local_communicator, ierr )
  136. dims(1) = ntasks_y ! rows
  137. dims(2) = ntasks_x ! columns
  138. isperiodic(1) = .true.
  139. isperiodic(2) = .true.
  140. CALL mpi_cart_create( new_local_comm, 2, dims, isperiodic, .false., local_communicator_periodic, ierr )
  141. ! debug
  142. CALL mpi_comm_rank( local_communicator_periodic, mytask, ierr )
  143. CALL mpi_cart_coords( local_communicator_periodic, mytask, 2, coords, ierr )
  144. ! write(0,*)'periodic coords ',mytask, coords
  145. CALL mpi_comm_rank( local_communicator, mytask, ierr )
  146. CALL mpi_cart_coords( local_communicator, mytask, 2, coords, ierr )
  147. ! write(0,*)'non periodic coords ',mytask, coords
  148. mytask_x = coords(2) ! col task (x)
  149. mytask_y = coords(1) ! row task (y)
  150. CALL nl_set_nproc_x ( 1, ntasks_x )
  151. CALL nl_set_nproc_y ( 1, ntasks_y )
  152. ! 20061228 set up subcommunicators for processors in X, Y coords of mesh
  153. ! note that local_comm_x has all the processors in a row (X=0:nproc_x-1);
  154. ! in other words, local_comm_x has all the processes with the same rank in Y
  155. CALL MPI_Comm_dup( new_local_comm, comdup, ierr )
  156. IF ( ierr .NE. 0 ) CALL wrf_error_fatal('MPI_Comm_dup fails in 20061228 mod')
  157. CALL MPI_Comm_split(comdup,mytask_y,mytask,local_communicator_x,ierr)
  158. IF ( ierr .NE. 0 ) CALL wrf_error_fatal('MPI_Comm_split fails for x in 20061228 mod')
  159. CALL MPI_Comm_split(comdup,mytask_x,mytask,local_communicator_y,ierr)
  160. IF ( ierr .NE. 0 ) CALL wrf_error_fatal('MPI_Comm_split fails for y in 20061228 mod')
  161. ! end 20061228
  162. CALL wrf_set_dm_communicator ( local_communicator )
  163. #else
  164. ntasks = 1
  165. ntasks_x = 1
  166. ntasks_y = 1
  167. mytask = 0
  168. mytask_x = 0
  169. mytask_y = 0
  170. #endif
  171. RETURN
  172. END SUBROUTINE wrf_dm_initialize
  173. SUBROUTINE get_dm_max_halo_width( id, width )
  174. IMPLICIT NONE
  175. INTEGER, INTENT(IN) :: id
  176. INTEGER, INTENT(OUT) :: width
  177. IF ( id .EQ. 1 ) THEN ! this is coarse domain
  178. width = max_halo_width
  179. ELSE
  180. width = max_halo_width + 3
  181. ENDIF
  182. RETURN
  183. END SUBROUTINE get_dm_max_halo_width
  184. SUBROUTINE patch_domain_rsl_lite( id , parent, parent_id, &
  185. sd1 , ed1 , sp1 , ep1 , sm1 , em1 , &
  186. sd2 , ed2 , sp2 , ep2 , sm2 , em2 , &
  187. sd3 , ed3 , sp3 , ep3 , sm3 , em3 , &
  188. sp1x , ep1x , sm1x , em1x , &
  189. sp2x , ep2x , sm2x , em2x , &
  190. sp3x , ep3x , sm3x , em3x , &
  191. sp1y , ep1y , sm1y , em1y , &
  192. sp2y , ep2y , sm2y , em2y , &
  193. sp3y , ep3y , sm3y , em3y , &
  194. bdx , bdy )
  195. USE module_domain, ONLY : domain, head_grid, find_grid_by_id, alloc_space_field
  196. IMPLICIT NONE
  197. INTEGER, INTENT(IN) :: sd1 , ed1 , sd2 , ed2 , sd3 , ed3 , bdx , bdy
  198. INTEGER, INTENT(OUT) :: sp1 , ep1 , sp2 , ep2 , sp3 , ep3 , &
  199. sm1 , em1 , sm2 , em2 , sm3 , em3
  200. INTEGER, INTENT(OUT) :: sp1x , ep1x , sp2x , ep2x , sp3x , ep3x , &
  201. sm1x , em1x , sm2x , em2x , sm3x , em3x
  202. INTEGER, INTENT(OUT) :: sp1y , ep1y , sp2y , ep2y , sp3y , ep3y , &
  203. sm1y , em1y , sm2y , em2y , sm3y , em3y
  204. INTEGER, INTENT(IN) :: id, parent_id
  205. TYPE(domain),POINTER :: parent
  206. ! Local variables
  207. INTEGER :: ids, ide, jds, jde, kds, kde
  208. INTEGER :: ims, ime, jms, jme, kms, kme
  209. INTEGER :: ips, ipe, jps, jpe, kps, kpe
  210. INTEGER :: imsx, imex, jmsx, jmex, kmsx, kmex
  211. INTEGER :: ipsx, ipex, jpsx, jpex, kpsx, kpex
  212. INTEGER :: imsy, imey, jmsy, jmey, kmsy, kmey
  213. INTEGER :: ipsy, ipey, jpsy, jpey, kpsy, kpey
  214. INTEGER :: c_sd1 , c_ed1 , c_sd2 , c_ed2 , c_sd3 , c_ed3
  215. INTEGER :: c_sp1 , c_ep1 , c_sp2 , c_ep2 , c_sp3 , c_ep3 , &
  216. c_sm1 , c_em1 , c_sm2 , c_em2 , c_sm3 , c_em3
  217. INTEGER :: c_sp1x , c_ep1x , c_sp2x , c_ep2x , c_sp3x , c_ep3x , &
  218. c_sm1x , c_em1x , c_sm2x , c_em2x , c_sm3x , c_em3x
  219. INTEGER :: c_sp1y , c_ep1y , c_sp2y , c_ep2y , c_sp3y , c_ep3y , &
  220. c_sm1y , c_em1y , c_sm2y , c_em2y , c_sm3y , c_em3y
  221. INTEGER :: c_ids, c_ide, c_jds, c_jde, c_kds, c_kde
  222. INTEGER :: c_ims, c_ime, c_jms, c_jme, c_kms, c_kme
  223. INTEGER :: c_ips, c_ipe, c_jps, c_jpe, c_kps, c_kpe
  224. INTEGER :: idim , jdim , kdim , rem , a, b
  225. INTEGER :: i, j, ni, nj, Px, Py, P
  226. INTEGER :: parent_grid_ratio, i_parent_start, j_parent_start
  227. INTEGER :: shw
  228. INTEGER :: idim_cd, jdim_cd, ierr
  229. INTEGER :: max_dom
  230. TYPE(domain), POINTER :: intermediate_grid
  231. TYPE(domain), POINTER :: nest_grid
  232. CHARACTER*256 :: mess
  233. INTEGER parent_max_halo_width
  234. INTEGER thisdomain_max_halo_width
  235. SELECT CASE ( model_data_order )
  236. ! need to finish other cases
  237. CASE ( DATA_ORDER_ZXY )
  238. ids = sd2 ; ide = ed2
  239. jds = sd3 ; jde = ed3
  240. kds = sd1 ; kde = ed1
  241. CASE ( DATA_ORDER_XYZ )
  242. ids = sd1 ; ide = ed1
  243. jds = sd2 ; jde = ed2
  244. kds = sd3 ; kde = ed3
  245. CASE ( DATA_ORDER_XZY )
  246. ids = sd1 ; ide = ed1
  247. jds = sd3 ; jde = ed3
  248. kds = sd2 ; kde = ed2
  249. CASE ( DATA_ORDER_YXZ)
  250. ids = sd2 ; ide = ed2
  251. jds = sd1 ; jde = ed1
  252. kds = sd3 ; kde = ed3
  253. END SELECT
  254. CALL nl_get_max_dom( 1 , max_dom )
  255. CALL get_dm_max_halo_width( id , thisdomain_max_halo_width )
  256. IF ( id .GT. 1 ) THEN
  257. CALL get_dm_max_halo_width( parent%id , parent_max_halo_width )
  258. ENDIF
  259. CALL compute_memory_dims_rsl_lite ( id, thisdomain_max_halo_width, 0 , bdx, bdy, &
  260. ids, ide, jds, jde, kds, kde, &
  261. ims, ime, jms, jme, kms, kme, &
  262. imsx, imex, jmsx, jmex, kmsx, kmex, &
  263. imsy, imey, jmsy, jmey, kmsy, kmey, &
  264. ips, ipe, jps, jpe, kps, kpe, &
  265. ipsx, ipex, jpsx, jpex, kpsx, kpex, &
  266. ipsy, ipey, jpsy, jpey, kpsy, kpey )
  267. ! ensure that the every parent domain point has a full set of nested points under it
  268. ! even at the borders. Do this by making sure the number of nest points is a multiple of
  269. ! the nesting ratio. Note that this is important mostly to the intermediate domain, which
  270. ! is the subject of the scatter gather comms with the parent
  271. IF ( id .GT. 1 ) THEN
  272. CALL nl_get_parent_grid_ratio( id, parent_grid_ratio )
  273. if ( mod(ime,parent_grid_ratio) .NE. 0 ) ime = ime + parent_grid_ratio - mod(ime,parent_grid_ratio)
  274. if ( mod(jme,parent_grid_ratio) .NE. 0 ) jme = jme + parent_grid_ratio - mod(jme,parent_grid_ratio)
  275. ENDIF
  276. SELECT CASE ( model_data_order )
  277. CASE ( DATA_ORDER_ZXY )
  278. sp2 = ips ; ep2 = ipe ; sm2 = ims ; em2 = ime
  279. sp3 = jps ; ep3 = jpe ; sm3 = jms ; em3 = jme
  280. sp1 = kps ; ep1 = kpe ; sm1 = kms ; em1 = kme
  281. sp2x = ipsx ; ep2x = ipex ; sm2x = imsx ; em2x = imex
  282. sp3x = jpsx ; ep3x = jpex ; sm3x = jmsx ; em3x = jmex
  283. sp1x = kpsx ; ep1x = kpex ; sm1x = kmsx ; em1x = kmex
  284. sp2y = ipsy ; ep2y = ipey ; sm2y = imsy ; em2y = imey
  285. sp3y = jpsy ; ep3y = jpey ; sm3y = jmsy ; em3y = jmey
  286. sp1y = kpsy ; ep1y = kpey ; sm1y = kmsy ; em1y = kmey
  287. CASE ( DATA_ORDER_ZYX )
  288. sp3 = ips ; ep3 = ipe ; sm3 = ims ; em3 = ime
  289. sp2 = jps ; ep2 = jpe ; sm2 = jms ; em2 = jme
  290. sp1 = kps ; ep1 = kpe ; sm1 = kms ; em1 = kme
  291. sp3x = ipsx ; ep3x = ipex ; sm3x = imsx ; em3x = imex
  292. sp2x = jpsx ; ep2x = jpex ; sm2x = jmsx ; em2x = jmex
  293. sp1x = kpsx ; ep1x = kpex ; sm1x = kmsx ; em1x = kmex
  294. sp3y = ipsy ; ep3y = ipey ; sm3y = imsy ; em3y = imey
  295. sp2y = jpsy ; ep2y = jpey ; sm2y = jmsy ; em2y = jmey
  296. sp1y = kpsy ; ep1y = kpey ; sm1y = kmsy ; em1y = kmey
  297. CASE ( DATA_ORDER_XYZ )
  298. sp1 = ips ; ep1 = ipe ; sm1 = ims ; em1 = ime
  299. sp2 = jps ; ep2 = jpe ; sm2 = jms ; em2 = jme
  300. sp3 = kps ; ep3 = kpe ; sm3 = kms ; em3 = kme
  301. sp1x = ipsx ; ep1x = ipex ; sm1x = imsx ; em1x = imex
  302. sp2x = jpsx ; ep2x = jpex ; sm2x = jmsx ; em2x = jmex
  303. sp3x = kpsx ; ep3x = kpex ; sm3x = kmsx ; em3x = kmex
  304. sp1y = ipsy ; ep1y = ipey ; sm1y = imsy ; em1y = imey
  305. sp2y = jpsy ; ep2y = jpey ; sm2y = jmsy ; em2y = jmey
  306. sp3y = kpsy ; ep3y = kpey ; sm3y = kmsy ; em3y = kmey
  307. CASE ( DATA_ORDER_YXZ)
  308. sp2 = ips ; ep2 = ipe ; sm2 = ims ; em2 = ime
  309. sp1 = jps ; ep1 = jpe ; sm1 = jms ; em1 = jme
  310. sp3 = kps ; ep3 = kpe ; sm3 = kms ; em3 = kme
  311. sp2x = ipsx ; ep2x = ipex ; sm2x = imsx ; em2x = imex
  312. sp1x = jpsx ; ep1x = jpex ; sm1x = jmsx ; em1x = jmex
  313. sp3x = kpsx ; ep3x = kpex ; sm3x = kmsx ; em3x = kmex
  314. sp2y = ipsy ; ep2y = ipey ; sm2y = imsy ; em2y = imey
  315. sp1y = jpsy ; ep1y = jpey ; sm1y = jmsy ; em1y = jmey
  316. sp3y = kpsy ; ep3y = kpey ; sm3y = kmsy ; em3y = kmey
  317. CASE ( DATA_ORDER_XZY )
  318. sp1 = ips ; ep1 = ipe ; sm1 = ims ; em1 = ime
  319. sp3 = jps ; ep3 = jpe ; sm3 = jms ; em3 = jme
  320. sp2 = kps ; ep2 = kpe ; sm2 = kms ; em2 = kme
  321. sp1x = ipsx ; ep1x = ipex ; sm1x = imsx ; em1x = imex
  322. sp3x = jpsx ; ep3x = jpex ; sm3x = jmsx ; em3x = jmex
  323. sp2x = kpsx ; ep2x = kpex ; sm2x = kmsx ; em2x = kmex
  324. sp1y = ipsy ; ep1y = ipey ; sm1y = imsy ; em1y = imey
  325. sp3y = jpsy ; ep3y = jpey ; sm3y = jmsy ; em3y = jmey
  326. sp2y = kpsy ; ep2y = kpey ; sm2y = kmsy ; em2y = kmey
  327. CASE ( DATA_ORDER_YZX )
  328. sp3 = ips ; ep3 = ipe ; sm3 = ims ; em3 = ime
  329. sp1 = jps ; ep1 = jpe ; sm1 = jms ; em1 = jme
  330. sp2 = kps ; ep2 = kpe ; sm2 = kms ; em2 = kme
  331. sp3x = ipsx ; ep3x = ipex ; sm3x = imsx ; em3x = imex
  332. sp1x = jpsx ; ep1x = jpex ; sm1x = jmsx ; em1x = jmex
  333. sp2x = kpsx ; ep2x = kpex ; sm2x = kmsx ; em2x = kmex
  334. sp3y = ipsy ; ep3y = ipey ; sm3y = imsy ; em3y = imey
  335. sp1y = jpsy ; ep1y = jpey ; sm1y = jmsy ; em1y = jmey
  336. sp2y = kpsy ; ep2y = kpey ; sm2y = kmsy ; em2y = kmey
  337. END SELECT
  338. IF ( id.EQ.1 ) THEN
  339. WRITE(wrf_err_message,*)'*************************************'
  340. CALL wrf_message( TRIM(wrf_err_message) )
  341. WRITE(wrf_err_message,*)'Parent domain'
  342. CALL wrf_message( TRIM(wrf_err_message) )
  343. WRITE(wrf_err_message,*)'ids,ide,jds,jde ',ids,ide,jds,jde
  344. CALL wrf_message( TRIM(wrf_err_message) )
  345. WRITE(wrf_err_message,*)'ims,ime,jms,jme ',ims,ime,jms,jme
  346. CALL wrf_message( TRIM(wrf_err_message) )
  347. WRITE(wrf_err_message,*)'ips,ipe,jps,jpe ',ips,ipe,jps,jpe
  348. CALL wrf_message( TRIM(wrf_err_message) )
  349. WRITE(wrf_err_message,*)'*************************************'
  350. CALL wrf_message( TRIM(wrf_err_message) )
  351. ENDIF
  352. IF ( id .GT. 1 ) THEN
  353. CALL nl_get_shw( id, shw )
  354. CALL nl_get_i_parent_start( id , i_parent_start )
  355. CALL nl_get_j_parent_start( id , j_parent_start )
  356. CALL nl_get_parent_grid_ratio( id, parent_grid_ratio )
  357. SELECT CASE ( model_data_order )
  358. CASE ( DATA_ORDER_ZXY )
  359. idim = ed2-sd2+1
  360. jdim = ed3-sd3+1
  361. kdim = ed1-sd1+1
  362. c_kds = sd1 ; c_kde = ed1
  363. CASE ( DATA_ORDER_ZYX )
  364. idim = ed3-sd3+1
  365. jdim = ed2-sd2+1
  366. kdim = ed1-sd1+1
  367. c_kds = sd1 ; c_kde = ed1
  368. CASE ( DATA_ORDER_XYZ )
  369. idim = ed1-sd1+1
  370. jdim = ed2-sd2+1
  371. kdim = ed3-sd3+1
  372. c_kds = sd3 ; c_kde = ed3
  373. CASE ( DATA_ORDER_YXZ)
  374. idim = ed2-sd2+1
  375. jdim = ed1-sd1+1
  376. kdim = ed3-sd3+1
  377. c_kds = sd3 ; c_kde = ed3
  378. CASE ( DATA_ORDER_XZY )
  379. idim = ed1-sd1+1
  380. jdim = ed3-sd3+1
  381. kdim = ed2-sd2+1
  382. c_kds = sd2 ; c_kde = ed2
  383. CASE ( DATA_ORDER_YZX )
  384. idim = ed3-sd3+1
  385. jdim = ed1-sd1+1
  386. kdim = ed2-sd2+1
  387. c_kds = sd2 ; c_kde = ed2
  388. END SELECT
  389. idim_cd = idim / parent_grid_ratio + 1 + 2*shw + 1
  390. jdim_cd = jdim / parent_grid_ratio + 1 + 2*shw + 1
  391. c_ids = i_parent_start-shw ; c_ide = c_ids + idim_cd - 1
  392. c_jds = j_parent_start-shw ; c_jde = c_jds + jdim_cd - 1
  393. ! we want the intermediate domain to be decomposed the
  394. ! the same as the underlying nest. So try this:
  395. c_ips = -1
  396. nj = ( c_jds - j_parent_start ) * parent_grid_ratio + 1 + 1 ;
  397. ierr = 0
  398. DO i = c_ids, c_ide
  399. ni = ( i - i_parent_start ) * parent_grid_ratio + 1 + 1 ;
  400. CALL task_for_point ( ni, nj, ids, ide, jds, jde, ntasks_x, ntasks_y, Px, Py, &
  401. 1, 1, ierr )
  402. IF ( Px .EQ. mytask_x ) THEN
  403. c_ipe = i
  404. IF ( c_ips .EQ. -1 ) c_ips = i
  405. ENDIF
  406. ENDDO
  407. IF ( ierr .NE. 0 ) THEN
  408. CALL tfp_message(__FILE__,__LINE__)
  409. ENDIF
  410. IF (c_ips .EQ. -1 ) THEN
  411. c_ipe = -1
  412. c_ips = 0
  413. ENDIF
  414. c_jps = -1
  415. ni = ( c_ids - i_parent_start ) * parent_grid_ratio + 1 + 1 ;
  416. ierr = 0
  417. DO j = c_jds, c_jde
  418. nj = ( j - j_parent_start ) * parent_grid_ratio + 1 + 1 ;
  419. CALL task_for_point ( ni, nj, ids, ide, jds, jde, ntasks_x, ntasks_y, Px, Py, &
  420. 1, 1, ierr )
  421. IF ( Py .EQ. mytask_y ) THEN
  422. c_jpe = j
  423. IF ( c_jps .EQ. -1 ) c_jps = j
  424. ENDIF
  425. ENDDO
  426. IF ( ierr .NE. 0 ) THEN
  427. CALL tfp_message(__FILE__,__LINE__)
  428. ENDIF
  429. IF (c_jps .EQ. -1 ) THEN
  430. c_jpe = -1
  431. c_jps = 0
  432. ENDIF
  433. IF ( c_ips <= c_ipe ) THEN
  434. ! extend the patch dimensions out shw along edges of domain
  435. IF ( mytask_x .EQ. 0 ) THEN
  436. c_ips = c_ips - shw
  437. ENDIF
  438. IF ( mytask_x .EQ. ntasks_x-1 ) THEN
  439. c_ipe = c_ipe + shw
  440. ENDIF
  441. c_ims = max( c_ips - max(shw,thisdomain_max_halo_width), c_ids - bdx ) - 1
  442. c_ime = min( c_ipe + max(shw,thisdomain_max_halo_width), c_ide + bdx ) + 1
  443. ELSE
  444. c_ims = 0
  445. c_ime = 0
  446. ENDIF
  447. ! handle j dims
  448. IF ( c_jps <= c_jpe ) THEN
  449. ! extend the patch dimensions out shw along edges of domain
  450. IF ( mytask_y .EQ. 0 ) THEN
  451. c_jps = c_jps - shw
  452. ENDIF
  453. IF ( mytask_y .EQ. ntasks_y-1 ) THEN
  454. c_jpe = c_jpe + shw
  455. ENDIF
  456. c_jms = max( c_jps - max(shw,thisdomain_max_halo_width), c_jds - bdx ) - 1
  457. c_jme = min( c_jpe + max(shw,thisdomain_max_halo_width), c_jde + bdx ) + 1
  458. ! handle k dims
  459. ELSE
  460. c_jms = 0
  461. c_jme = 0
  462. ENDIF
  463. c_kps = 1
  464. c_kpe = c_kde
  465. c_kms = 1
  466. c_kme = c_kde
  467. WRITE(wrf_err_message,*)'*************************************'
  468. CALL wrf_message( TRIM(wrf_err_message) )
  469. WRITE(wrf_err_message,*)'Nesting domain'
  470. CALL wrf_message( TRIM(wrf_err_message) )
  471. WRITE(wrf_err_message,*)'ids,ide,jds,jde ',ids,ide,jds,jde
  472. CALL wrf_message( TRIM(wrf_err_message) )
  473. WRITE(wrf_err_message,*)'ims,ime,jms,jme ',ims,ime,jms,jme
  474. CALL wrf_message( TRIM(wrf_err_message) )
  475. WRITE(wrf_err_message,*)'ips,ipe,jps,jpe ',ips,ipe,jps,jpe
  476. CALL wrf_message( TRIM(wrf_err_message) )
  477. WRITE(wrf_err_message,*)'INTERMEDIATE domain'
  478. CALL wrf_message( TRIM(wrf_err_message) )
  479. WRITE(wrf_err_message,*)'ids,ide,jds,jde ',c_ids,c_ide,c_jds,c_jde
  480. CALL wrf_message( TRIM(wrf_err_message) )
  481. WRITE(wrf_err_message,*)'ims,ime,jms,jme ',c_ims,c_ime,c_jms,c_jme
  482. CALL wrf_message( TRIM(wrf_err_message) )
  483. WRITE(wrf_err_message,*)'ips,ipe,jps,jpe ',c_ips,c_ipe,c_jps,c_jpe
  484. CALL wrf_message( TRIM(wrf_err_message) )
  485. WRITE(wrf_err_message,*)'*************************************'
  486. CALL wrf_message( TRIM(wrf_err_message) )
  487. SELECT CASE ( model_data_order )
  488. CASE ( DATA_ORDER_ZXY )
  489. c_sd2 = c_ids ; c_ed2 = c_ide ; c_sp2 = c_ips ; c_ep2 = c_ipe ; c_sm2 = c_ims ; c_em2 = c_ime
  490. c_sd3 = c_jds ; c_ed3 = c_jde ; c_sp3 = c_jps ; c_ep3 = c_jpe ; c_sm3 = c_jms ; c_em3 = c_jme
  491. c_sd1 = c_kds ; c_ed1 = c_kde ; c_sp1 = c_kps ; c_ep1 = c_kpe ; c_sm1 = c_kms ; c_em1 = c_kme
  492. CASE ( DATA_ORDER_ZYX )
  493. c_sd3 = c_ids ; c_ed3 = c_ide ; c_sp3 = c_ips ; c_ep3 = c_ipe ; c_sm3 = c_ims ; c_em3 = c_ime
  494. c_sd2 = c_jds ; c_ed2 = c_jde ; c_sp2 = c_jps ; c_ep2 = c_jpe ; c_sm2 = c_jms ; c_em2 = c_jme
  495. c_sd1 = c_kds ; c_ed1 = c_kde ; c_sp1 = c_kps ; c_ep1 = c_kpe ; c_sm1 = c_kms ; c_em1 = c_kme
  496. CASE ( DATA_ORDER_XYZ )
  497. c_sd1 = c_ids ; c_ed1 = c_ide ; c_sp1 = c_ips ; c_ep1 = c_ipe ; c_sm1 = c_ims ; c_em1 = c_ime
  498. c_sd2 = c_jds ; c_ed2 = c_jde ; c_sp2 = c_jps ; c_ep2 = c_jpe ; c_sm2 = c_jms ; c_em2 = c_jme
  499. c_sd3 = c_kds ; c_ed3 = c_kde ; c_sp3 = c_kps ; c_ep3 = c_kpe ; c_sm3 = c_kms ; c_em3 = c_kme
  500. CASE ( DATA_ORDER_YXZ)
  501. c_sd2 = c_ids ; c_ed2 = c_ide ; c_sp2 = c_ips ; c_ep2 = c_ipe ; c_sm2 = c_ims ; c_em2 = c_ime
  502. c_sd1 = c_jds ; c_ed1 = c_jde ; c_sp1 = c_jps ; c_ep1 = c_jpe ; c_sm1 = c_jms ; c_em1 = c_jme
  503. c_sd3 = c_kds ; c_ed3 = c_kde ; c_sp3 = c_kps ; c_ep3 = c_kpe ; c_sm3 = c_kms ; c_em3 = c_kme
  504. CASE ( DATA_ORDER_XZY )
  505. c_sd1 = c_ids ; c_ed1 = c_ide ; c_sp1 = c_ips ; c_ep1 = c_ipe ; c_sm1 = c_ims ; c_em1 = c_ime
  506. c_sd3 = c_jds ; c_ed3 = c_jde ; c_sp3 = c_jps ; c_ep3 = c_jpe ; c_sm3 = c_jms ; c_em3 = c_jme
  507. c_sd2 = c_kds ; c_ed2 = c_kde ; c_sp2 = c_kps ; c_ep2 = c_kpe ; c_sm2 = c_kms ; c_em2 = c_kme
  508. CASE ( DATA_ORDER_YZX )
  509. c_sd3 = c_ids ; c_ed3 = c_ide ; c_sp3 = c_ips ; c_ep3 = c_ipe ; c_sm3 = c_ims ; c_em3 = c_ime
  510. c_sd1 = c_jds ; c_ed1 = c_jde ; c_sp1 = c_jps ; c_ep1 = c_jpe ; c_sm1 = c_jms ; c_em1 = c_jme
  511. c_sd2 = c_kds ; c_ed2 = c_kde ; c_sp2 = c_kps ; c_ep2 = c_kpe ; c_sm2 = c_kms ; c_em2 = c_kme
  512. END SELECT
  513. ALLOCATE ( intermediate_grid )
  514. ALLOCATE ( intermediate_grid%parents( max_parents ) )
  515. ALLOCATE ( intermediate_grid%nests( max_nests ) )
  516. intermediate_grid%allocated=.false.
  517. NULLIFY( intermediate_grid%sibling )
  518. DO i = 1, max_nests
  519. NULLIFY( intermediate_grid%nests(i)%ptr )
  520. ENDDO
  521. NULLIFY (intermediate_grid%next)
  522. NULLIFY (intermediate_grid%same_level)
  523. NULLIFY (intermediate_grid%i_start)
  524. NULLIFY (intermediate_grid%j_start)
  525. NULLIFY (intermediate_grid%i_end)
  526. NULLIFY (intermediate_grid%j_end)
  527. intermediate_grid%id = id ! these must be the same. Other parts of code depend on it (see gen_comms.c)
  528. intermediate_grid%num_nests = 0
  529. intermediate_grid%num_siblings = 0
  530. intermediate_grid%num_parents = 1
  531. intermediate_grid%max_tiles = 0
  532. intermediate_grid%num_tiles_spec = 0
  533. CALL find_grid_by_id ( id, head_grid, nest_grid )
  534. nest_grid%intermediate_grid => intermediate_grid ! nest grid now has a pointer to this baby
  535. intermediate_grid%parents(1)%ptr => nest_grid ! the intermediate grid considers nest its parent
  536. intermediate_grid%num_parents = 1
  537. intermediate_grid%is_intermediate = .TRUE.
  538. SELECT CASE ( model_data_order )
  539. CASE ( DATA_ORDER_ZXY )
  540. intermediate_grid%nids = nest_grid%sd32 ; intermediate_grid%njds = nest_grid%sd33
  541. intermediate_grid%nide = nest_grid%ed32 ; intermediate_grid%njde = nest_grid%sd33
  542. CASE ( DATA_ORDER_ZYX )
  543. intermediate_grid%nids = nest_grid%sd33 ; intermediate_grid%njds = nest_grid%sd32
  544. intermediate_grid%nide = nest_grid%ed33 ; intermediate_grid%njde = nest_grid%sd32
  545. CASE ( DATA_ORDER_XYZ )
  546. intermediate_grid%nids = nest_grid%sd31 ; intermediate_grid%njds = nest_grid%sd32
  547. intermediate_grid%nide = nest_grid%ed31 ; intermediate_grid%njde = nest_grid%sd32
  548. CASE ( DATA_ORDER_YXZ)
  549. intermediate_grid%nids = nest_grid%sd32 ; intermediate_grid%njds = nest_grid%sd31
  550. intermediate_grid%nide = nest_grid%ed32 ; intermediate_grid%njde = nest_grid%sd31
  551. CASE ( DATA_ORDER_XZY )
  552. intermediate_grid%nids = nest_grid%sd31 ; intermediate_grid%njds = nest_grid%sd33
  553. intermediate_grid%nide = nest_grid%ed31 ; intermediate_grid%njde = nest_grid%sd33
  554. CASE ( DATA_ORDER_YZX )
  555. intermediate_grid%nids = nest_grid%sd33 ; intermediate_grid%njds = nest_grid%sd31
  556. intermediate_grid%nide = nest_grid%ed33 ; intermediate_grid%njde = nest_grid%sd31
  557. END SELECT
  558. intermediate_grid%nids = ids
  559. intermediate_grid%nide = ide
  560. intermediate_grid%njds = jds
  561. intermediate_grid%njde = jde
  562. c_sm1x = 1 ; c_em1x = 1 ; c_sm2x = 1 ; c_em2x = 1 ; c_sm3x = 1 ; c_em3x = 1
  563. c_sm1y = 1 ; c_em1y = 1 ; c_sm2y = 1 ; c_em2y = 1 ; c_sm3y = 1 ; c_em3y = 1
  564. intermediate_grid%sm31x = c_sm1x
  565. intermediate_grid%em31x = c_em1x
  566. intermediate_grid%sm32x = c_sm2x
  567. intermediate_grid%em32x = c_em2x
  568. intermediate_grid%sm33x = c_sm3x
  569. intermediate_grid%em33x = c_em3x
  570. intermediate_grid%sm31y = c_sm1y
  571. intermediate_grid%em31y = c_em1y
  572. intermediate_grid%sm32y = c_sm2y
  573. intermediate_grid%em32y = c_em2y
  574. intermediate_grid%sm33y = c_sm3y
  575. intermediate_grid%em33y = c_em3y
  576. #if ( defined(SGIALTIX) && (! defined(MOVE_NESTS) ) ) || ( defined(FUJITSU_FX10) && (! defined(MOVE_NESTS) ) )
  577. ! allocate space for the intermediate domain
  578. CALL alloc_space_field ( intermediate_grid, intermediate_grid%id , 1, 2 , .TRUE., & ! use same id as nest
  579. c_sd1, c_ed1, c_sd2, c_ed2, c_sd3, c_ed3, &
  580. c_sm1, c_em1, c_sm2, c_em2, c_sm3, c_em3, &
  581. c_sp1, c_ep1, c_sp2, c_ep2, c_sp3, c_ep3, &
  582. c_sm1x, c_em1x, c_sm2x, c_em2x, c_sm3x, c_em3x, &
  583. c_sm1y, c_em1y, c_sm2y, c_em2y, c_sm3y, c_em3y, &
  584. c_sm1x, c_em1x, c_sm2x, c_em2x, c_sm3x, c_em3x, & ! x-xpose
  585. c_sm1y, c_em1y, c_sm2y, c_em2y, c_sm3y, c_em3y ) ! y-xpose
  586. #endif
  587. intermediate_grid%sd31 = c_sd1
  588. intermediate_grid%ed31 = c_ed1
  589. intermediate_grid%sp31 = c_sp1
  590. intermediate_grid%ep31 = c_ep1
  591. intermediate_grid%sm31 = c_sm1
  592. intermediate_grid%em31 = c_em1
  593. intermediate_grid%sd32 = c_sd2
  594. intermediate_grid%ed32 = c_ed2
  595. intermediate_grid%sp32 = c_sp2
  596. intermediate_grid%ep32 = c_ep2
  597. intermediate_grid%sm32 = c_sm2
  598. intermediate_grid%em32 = c_em2
  599. intermediate_grid%sd33 = c_sd3
  600. intermediate_grid%ed33 = c_ed3
  601. intermediate_grid%sp33 = c_sp3
  602. intermediate_grid%ep33 = c_ep3
  603. intermediate_grid%sm33 = c_sm3
  604. intermediate_grid%em33 = c_em3
  605. CALL med_add_config_info_to_grid ( intermediate_grid )
  606. intermediate_grid%dx = parent%dx
  607. intermediate_grid%dy = parent%dy
  608. intermediate_grid%dt = parent%dt
  609. ENDIF
  610. RETURN
  611. END SUBROUTINE patch_domain_rsl_lite
  612. SUBROUTINE compute_memory_dims_rsl_lite ( &
  613. id , maxhalowidth , &
  614. shw , bdx, bdy , &
  615. ids, ide, jds, jde, kds, kde, &
  616. ims, ime, jms, jme, kms, kme, &
  617. imsx, imex, jmsx, jmex, kmsx, kmex, &
  618. imsy, imey, jmsy, jmey, kmsy, kmey, &
  619. ips, ipe, jps, jpe, kps, kpe, &
  620. ipsx, ipex, jpsx, jpex, kpsx, kpex, &
  621. ipsy, ipey, jpsy, jpey, kpsy, kpey )
  622. IMPLICIT NONE
  623. INTEGER, INTENT(IN) :: id , maxhalowidth
  624. INTEGER, INTENT(IN) :: shw, bdx, bdy
  625. INTEGER, INTENT(IN) :: ids, ide, jds, jde, kds, kde
  626. INTEGER, INTENT(OUT) :: ims, ime, jms, jme, kms, kme
  627. INTEGER, INTENT(OUT) :: imsx, imex, jmsx, jmex, kmsx, kmex
  628. INTEGER, INTENT(OUT) :: imsy, imey, jmsy, jmey, kmsy, kmey
  629. INTEGER, INTENT(OUT) :: ips, ipe, jps, jpe, kps, kpe
  630. INTEGER, INTENT(OUT) :: ipsx, ipex, jpsx, jpex, kpsx, kpex
  631. INTEGER, INTENT(OUT) :: ipsy, ipey, jpsy, jpey, kpsy, kpey
  632. INTEGER Px, Py, P, i, j, k, ierr
  633. #if ( ! NMM_CORE == 1 )
  634. ! xy decomposition
  635. ips = -1
  636. j = jds
  637. ierr = 0
  638. DO i = ids, ide
  639. CALL task_for_point ( i, j, ids, ide, jds, jde, ntasks_x, ntasks_y, Px, Py, &
  640. 1, 1, ierr )
  641. IF ( Px .EQ. mytask_x ) THEN
  642. ipe = i
  643. IF ( ips .EQ. -1 ) ips = i
  644. ENDIF
  645. ENDDO
  646. IF ( ierr .NE. 0 ) THEN
  647. CALL tfp_message(__FILE__,__LINE__)
  648. ENDIF
  649. ! handle setting the memory dimensions where there are no X elements assigned to this proc
  650. IF (ips .EQ. -1 ) THEN
  651. ipe = -1
  652. ips = 0
  653. ENDIF
  654. jps = -1
  655. i = ids
  656. ierr = 0
  657. DO j = jds, jde
  658. CALL task_for_point ( i, j, ids, ide, jds, jde, ntasks_x, ntasks_y, Px, Py, &
  659. 1, 1, ierr )
  660. IF ( Py .EQ. mytask_y ) THEN
  661. jpe = j
  662. IF ( jps .EQ. -1 ) jps = j
  663. ENDIF
  664. ENDDO
  665. IF ( ierr .NE. 0 ) THEN
  666. CALL tfp_message(__FILE__,__LINE__)
  667. ENDIF
  668. ! handle setting the memory dimensions where there are no Y elements assigned to this proc
  669. IF (jps .EQ. -1 ) THEN
  670. jpe = -1
  671. jps = 0
  672. ENDIF
  673. !begin: wig; 12-Mar-2008
  674. ! This appears redundant with the conditionals above, but we get cases with only
  675. ! one of the directions being set to "missing" when turning off extra processors.
  676. ! This may break the handling of setting only one of nproc_x or nproc_y via the namelist.
  677. IF (ipe .EQ. -1 .or. jpe .EQ. -1) THEN
  678. ipe = -1
  679. ips = 0
  680. jpe = -1
  681. jps = 0
  682. ENDIF
  683. !end: wig; 12-Mar-2008
  684. !
  685. ! description of transpose decomposition strategy for RSL LITE. 20061231jm
  686. !
  687. ! Here is the tranpose scheme that is implemented for RSL_LITE. Upper-case
  688. ! XY corresponds to the dimension of the processor mesh, lower-case xyz
  689. ! corresponds to grid dimension.
  690. !
  691. ! xy zy zx
  692. !
  693. ! XxYy <--> XzYy <--> XzYx <- note x decomposed over Y procs
  694. ! ^ ^
  695. ! | |
  696. ! +------------------+ <- this edge is costly; see below
  697. !
  698. ! The aim is to avoid all-to-all communication over whole
  699. ! communicator. Instead, when possible, use a transpose scheme that requires
  700. ! all-to-all within dimensional communicators; that is, communicators
  701. ! defined for the processes in a rank or column of the processor mesh. Note,
  702. ! however, it is not possible to create a ring of transposes between
  703. ! xy-yz-xz decompositions without at least one of the edges in the ring
  704. ! being fully all-to-all (in other words, one of the tranpose edges must
  705. ! rotate and not just transpose a plane of the model grid within the
  706. ! processor mesh). The issue is then, where should we put this costly edge
  707. ! in the tranpose scheme we chose? To avoid being completely arbitrary,
  708. ! we chose a scheme most natural for models that use parallel spectral
  709. ! transforms, where the costly edge is the one that goes from the xz to
  710. ! the xy decomposition. (May be implemented as just a two step transpose
  711. ! back through yz).
  712. !
  713. ! Additional notational convention, below. The 'x' or 'y' appended to the
  714. ! dimension start or end variable refers to which grid dimension is all
  715. ! on-processor in the given decomposition. That is ipsx and ipex are the
  716. ! start and end for the i-dimension in the zy decomposition where x is
  717. ! on-processor. ('z' is assumed for xy decomposition and not appended to
  718. ! the ips, ipe, etc. variable names).
  719. !
  720. ! XzYy decomposition
  721. kpsx = -1
  722. j = jds ;
  723. ierr = 0
  724. DO k = kds, kde
  725. CALL task_for_point ( k, j, kds, kde, jds, jde, ntasks_x, ntasks_y, Px, Py, &
  726. 1, 1, ierr )
  727. IF ( Px .EQ. mytask_x ) THEN
  728. kpex = k
  729. IF ( kpsx .EQ. -1 ) kpsx = k
  730. ENDIF
  731. ENDDO
  732. IF ( ierr .NE. 0 ) THEN
  733. CALL tfp_message(__FILE__,__LINE__)
  734. ENDIF
  735. ! handle case where no levels are assigned to this process
  736. ! no iterations. Do same for I and J. Need to handle memory alloc below.
  737. IF (kpsx .EQ. -1 ) THEN
  738. kpex = -1
  739. kpsx = 0
  740. ENDIF
  741. jpsx = -1
  742. k = kds ;
  743. ierr = 0
  744. DO j = jds, jde
  745. CALL task_for_point ( k, j, kds, kde, jds, jde, ntasks_x, ntasks_y, Px, Py, &
  746. 1, 1, ierr )
  747. IF ( Py .EQ. mytask_y ) THEN
  748. jpex = j
  749. IF ( jpsx .EQ. -1 ) jpsx = j
  750. ENDIF
  751. ENDDO
  752. IF ( ierr .NE. 0 ) THEN
  753. CALL tfp_message(__FILE__,__LINE__)
  754. ENDIF
  755. IF (jpsx .EQ. -1 ) THEN
  756. jpex = -1
  757. jpsx = 0
  758. ENDIF
  759. !begin: wig; 12-Mar-2008
  760. ! This appears redundant with the conditionals above, but we get cases with only
  761. ! one of the directions being set to "missing" when turning off extra processors.
  762. ! This may break the handling of setting only one of nproc_x or nproc_y via the namelist.
  763. IF (ipex .EQ. -1 .or. jpex .EQ. -1) THEN
  764. ipex = -1
  765. ipsx = 0
  766. jpex = -1
  767. jpsx = 0
  768. ENDIF
  769. !end: wig; 12-Mar-2008
  770. ! XzYx decomposition (note, x grid dim is decomposed over Y processor dim)
  771. kpsy = kpsx ! same as above
  772. kpey = kpex ! same as above
  773. ipsy = -1
  774. k = kds ;
  775. ierr = 0
  776. DO i = ids, ide
  777. CALL task_for_point ( i, k, ids, ide, kds, kde, ntasks_y, ntasks_x, Py, Px, &
  778. 1, 1, ierr ) ! x and y for proc mesh reversed
  779. IF ( Py .EQ. mytask_y ) THEN
  780. ipey = i
  781. IF ( ipsy .EQ. -1 ) ipsy = i
  782. ENDIF
  783. ENDDO
  784. IF ( ierr .NE. 0 ) THEN
  785. CALL tfp_message(__FILE__,__LINE__)
  786. ENDIF
  787. IF (ipsy .EQ. -1 ) THEN
  788. ipey = -1
  789. ipsy = 0
  790. ENDIF
  791. #else
  792. ! In case of NMM CORE, the domain only ever runs from ids..ide-1 and jds..jde-1 so
  793. ! adjust decomposition to reflect. 20051020 JM
  794. ips = -1
  795. j = jds
  796. ierr = 0
  797. DO i = ids, ide-1
  798. CALL task_for_point ( i, j, ids, ide-1, jds, jde-1, ntasks_x, ntasks_y, Px, Py, &
  799. 1, 1 , ierr )
  800. IF ( Px .EQ. mytask_x ) THEN
  801. ipe = i
  802. IF ( Px .EQ. ntasks_x-1 ) ipe = ipe + 1
  803. IF ( ips .EQ. -1 ) ips = i
  804. ENDIF
  805. ENDDO
  806. IF ( ierr .NE. 0 ) THEN
  807. CALL tfp_message(__FILE__,__LINE__)
  808. ENDIF
  809. jps = -1
  810. i = ids ;
  811. ierr = 0
  812. DO j = jds, jde-1
  813. CALL task_for_point ( i, j, ids, ide-1, jds, jde-1, ntasks_x, ntasks_y, Px, Py, &
  814. 1 , 1 , ierr )
  815. IF ( Py .EQ. mytask_y ) THEN
  816. jpe = j
  817. IF ( Py .EQ. ntasks_y-1 ) jpe = jpe + 1
  818. IF ( jps .EQ. -1 ) jps = j
  819. ENDIF
  820. ENDDO
  821. IF ( ierr .NE. 0 ) THEN
  822. CALL tfp_message(__FILE__,__LINE__)
  823. ENDIF
  824. #endif
  825. ! extend the patch dimensions out shw along edges of domain
  826. IF ( ips < ipe .and. jps < jpe ) THEN !wig; 11-Mar-2008
  827. IF ( mytask_x .EQ. 0 ) THEN
  828. ips = ips - shw
  829. ipsy = ipsy - shw
  830. ENDIF
  831. IF ( mytask_x .EQ. ntasks_x-1 ) THEN
  832. ipe = ipe + shw
  833. ipey = ipey + shw
  834. ENDIF
  835. IF ( mytask_y .EQ. 0 ) THEN
  836. jps = jps - shw
  837. jpsx = jpsx - shw
  838. ENDIF
  839. IF ( mytask_y .EQ. ntasks_y-1 ) THEN
  840. jpe = jpe + shw
  841. jpex = jpex + shw
  842. ENDIF
  843. ENDIF !wig; 11-Mar-2008
  844. kps = 1
  845. kpe = kde-kds+1
  846. kms = 1
  847. kme = kpe
  848. kmsx = kpsx
  849. kmex = kpex
  850. kmsy = kpsy
  851. kmey = kpey
  852. ! handle setting the memory dimensions where there are no levels assigned to this proc
  853. IF ( kpsx .EQ. 0 .AND. kpex .EQ. -1 ) THEN
  854. kmsx = 0
  855. kmex = 0
  856. ENDIF
  857. IF ( kpsy .EQ. 0 .AND. kpey .EQ. -1 ) THEN
  858. kmsy = 0
  859. kmey = 0
  860. ENDIF
  861. IF ( (jps .EQ. 0 .AND. jpe .EQ. -1) .OR. (ips .EQ. 0 .AND. ipe .EQ. -1) ) THEN
  862. ims = 0
  863. ime = 0
  864. ELSE
  865. ims = max( ips - max(shw,maxhalowidth), ids - bdx ) - 1
  866. ime = min( ipe + max(shw,maxhalowidth), ide + bdx ) + 1
  867. ENDIF
  868. imsx = ids
  869. imex = ide
  870. ipsx = imsx
  871. ipex = imex
  872. ! handle setting the memory dimensions where there are no Y elements assigned to this proc
  873. IF ( ipsy .EQ. 0 .AND. ipey .EQ. -1 ) THEN
  874. imsy = 0
  875. imey = 0
  876. ELSE
  877. imsy = ipsy
  878. imey = ipey
  879. ENDIF
  880. IF ( (jps .EQ. 0 .AND. jpe .EQ. -1) .OR. (ips .EQ. 0 .AND. ipe .EQ. -1) ) THEN
  881. jms = 0
  882. jme = 0
  883. ELSE
  884. jms = max( jps - max(shw,maxhalowidth), jds - bdy ) - 1
  885. jme = min( jpe + max(shw,maxhalowidth), jde + bdy ) + 1
  886. ENDIF
  887. jmsx = jpsx
  888. jmex = jpex
  889. jmsy = jds
  890. jmey = jde
  891. ! handle setting the memory dimensions where there are no X elements assigned to this proc
  892. IF ( jpsx .EQ. 0 .AND. jpex .EQ. -1 ) THEN
  893. jmsx = 0
  894. jmex = 0
  895. ELSE
  896. jpsy = jmsy
  897. jpey = jmey
  898. ENDIF
  899. END SUBROUTINE compute_memory_dims_rsl_lite
  900. ! internal, used below for switching the argument to MPI calls
  901. ! if reals are being autopromoted to doubles in the build of WRF
  902. INTEGER function getrealmpitype()
  903. #ifndef STUBMPI
  904. IMPLICIT NONE
  905. INCLUDE 'mpif.h'
  906. INTEGER rtypesize, dtypesize, ierr
  907. CALL mpi_type_size ( MPI_REAL, rtypesize, ierr )
  908. CALL mpi_type_size ( MPI_DOUBLE_PRECISION, dtypesize, ierr )
  909. IF ( RWORDSIZE .EQ. rtypesize ) THEN
  910. getrealmpitype = MPI_REAL
  911. ELSE IF ( RWORDSIZE .EQ. dtypesize ) THEN
  912. getrealmpitype = MPI_DOUBLE_PRECISION
  913. ELSE
  914. CALL wrf_error_fatal ( 'RWORDSIZE or DWORDSIZE does not match any MPI type' )
  915. ENDIF
  916. #else
  917. ! required dummy initialization for function that is never called
  918. getrealmpitype = 1
  919. #endif
  920. RETURN
  921. END FUNCTION getrealmpitype
  922. REAL FUNCTION wrf_dm_max_real ( inval )
  923. IMPLICIT NONE
  924. #ifndef STUBMPI
  925. INCLUDE 'mpif.h'
  926. REAL inval, retval
  927. INTEGER ierr
  928. CALL mpi_allreduce ( inval, retval , 1, getrealmpitype(), MPI_MAX, local_communicator, ierr )
  929. wrf_dm_max_real = retval
  930. #else
  931. REAL inval
  932. wrf_dm_max_real = inval
  933. #endif
  934. END FUNCTION wrf_dm_max_real
  935. REAL FUNCTION wrf_dm_min_real ( inval )
  936. IMPLICIT NONE
  937. #ifndef STUBMPI
  938. INCLUDE 'mpif.h'
  939. REAL inval, retval
  940. INTEGER ierr
  941. CALL mpi_allreduce ( inval, retval , 1, getrealmpitype(), MPI_MIN, local_communicator, ierr )
  942. wrf_dm_min_real = retval
  943. #else
  944. REAL inval
  945. wrf_dm_min_real = inval
  946. #endif
  947. END FUNCTION wrf_dm_min_real
  948. SUBROUTINE wrf_dm_min_reals ( inval, retval, n )
  949. IMPLICIT NONE
  950. INTEGER n
  951. REAL inval(*)
  952. REAL retval(*)
  953. #ifndef STUBMPI
  954. INCLUDE 'mpif.h'
  955. INTEGER ierr
  956. CALL mpi_allreduce ( inval, retval , n, getrealmpitype(), MPI_MIN, local_communicator, ierr )
  957. #else
  958. retval(1:n) = inval(1:n)
  959. #endif
  960. END SUBROUTINE wrf_dm_min_reals
  961. REAL FUNCTION wrf_dm_sum_real ( inval )
  962. IMPLICIT NONE
  963. #ifndef STUBMPI
  964. INCLUDE 'mpif.h'
  965. REAL inval, retval
  966. INTEGER ierr
  967. CALL mpi_allreduce ( inval, retval , 1, getrealmpitype(), MPI_SUM, local_communicator, ierr )
  968. wrf_dm_sum_real = retval
  969. #else
  970. REAL inval
  971. wrf_dm_sum_real = inval
  972. #endif
  973. END FUNCTION wrf_dm_sum_real
  974. SUBROUTINE wrf_dm_sum_reals (inval, retval)
  975. IMPLICIT NONE
  976. REAL, INTENT(IN) :: inval(:)
  977. REAL, INTENT(OUT) :: retval(:)
  978. #ifndef STUBMPI
  979. INCLUDE 'mpif.h'
  980. INTEGER ierr
  981. CALL mpi_allreduce ( inval, retval, SIZE(inval), getrealmpitype(), MPI_SUM, local_communicator, ierr )
  982. #else
  983. retval = inval
  984. #endif
  985. END SUBROUTINE wrf_dm_sum_reals
  986. INTEGER FUNCTION wrf_dm_sum_integer ( inval )
  987. IMPLICIT NONE
  988. #ifndef STUBMPI
  989. INCLUDE 'mpif.h'
  990. INTEGER inval, retval
  991. INTEGER ierr
  992. CALL mpi_allreduce ( inval, retval , 1, MPI_INTEGER, MPI_SUM, local_communicator, ierr )
  993. wrf_dm_sum_integer = retval
  994. #else
  995. INTEGER inval
  996. wrf_dm_sum_integer = inval
  997. #endif
  998. END FUNCTION wrf_dm_sum_integer
  999. #ifdef HWRF
  1000. SUBROUTINE wrf_dm_minloc_real ( val, lat, lon, z, idex, jdex )
  1001. IMPLICIT NONE
  1002. #ifndef STUBMPI
  1003. INCLUDE 'mpif.h'
  1004. REAL val, lat, lon, z
  1005. INTEGER idex, jdex, ierr
  1006. INTEGER dex(2)
  1007. REAL vll(4)
  1008. INTEGER dex_all (2,ntasks)
  1009. REAL vll_all(4,ntasks)
  1010. INTEGER i
  1011. vll= (/ val, lat, lon, z /)
  1012. dex(1) = idex ; dex(2) = jdex
  1013. CALL mpi_allgather ( dex, 2, MPI_INTEGER, dex_all , 2, MPI_INTEGER, local_communicator, ierr )
  1014. CALL mpi_allgather ( vll, 4, getrealmpitype(), vll_all , 4, getrealmpitype(), local_communicator, ierr )
  1015. val = vll_all(1,1) ; lat = vll_all(2,1)
  1016. lon = vll_all(3,1) ; z = vll_all(4,1)
  1017. idex = dex_all(1,1) ; jdex = dex_all(2,1)
  1018. DO i = 2, ntasks
  1019. IF ( vll_all(1,i) .LT. val ) THEN
  1020. val = vll_all(1,i)
  1021. lat = vll_all(2,i)
  1022. lon = vll_all(3,i)
  1023. z = vll_all(4,i)
  1024. idex = dex_all(1,i)
  1025. jdex = dex_all(2,i)
  1026. ENDIF
  1027. ENDDO
  1028. #else
  1029. REAL val,lat,lon,z
  1030. INTEGER idex, jdex, ierr
  1031. #endif
  1032. END SUBROUTINE wrf_dm_minloc_real
  1033. SUBROUTINE wrf_dm_maxloc_real ( val, lat, lon, z, idex, jdex )
  1034. IMPLICIT NONE
  1035. #ifndef STUBMPI
  1036. INCLUDE 'mpif.h'
  1037. REAL val, lat, lon, z
  1038. INTEGER idex, jdex, ierr
  1039. INTEGER dex(2)
  1040. REAL vll(4)
  1041. INTEGER dex_all (2,ntasks)
  1042. REAL vll_all(4,ntasks)
  1043. INTEGER i
  1044. vll= (/ val, lat, lon, z /)
  1045. dex(1) = idex ; dex(2) = jdex
  1046. CALL mpi_allgather ( dex, 2, MPI_INTEGER, dex_all , 2, MPI_INTEGER, local_communicator, ierr )
  1047. CALL mpi_allgather ( vll, 4, getrealmpitype(), vll_all , 4, getrealmpitype(), local_communicator, ierr )
  1048. val = vll_all(1,1) ; lat = vll_all(2,1)
  1049. lon = vll_all(3,1) ; z = vll_all(4,1)
  1050. idex = dex_all(1,1) ; jdex = dex_all(2,1)
  1051. DO i = 2, ntasks
  1052. IF ( vll_all(1,i) .GT. val ) THEN
  1053. val = vll_all(1,i)
  1054. lat = vll_all(2,i)
  1055. lon = vll_all(3,i)
  1056. z = vll_all(4,i)
  1057. idex = dex_all(1,i)
  1058. jdex = dex_all(2,i)
  1059. ENDIF
  1060. ENDDO
  1061. #else
  1062. REAL val,lat,lon,z
  1063. INTEGER idex, jdex, ierr
  1064. #endif
  1065. END SUBROUTINE wrf_dm_maxloc_real
  1066. #endif
  1067. INTEGER FUNCTION wrf_dm_bxor_integer ( inval )
  1068. IMPLICIT NONE
  1069. #ifndef STUBMPI
  1070. INCLUDE 'mpif.h'
  1071. INTEGER inval, retval
  1072. INTEGER ierr
  1073. CALL mpi_allreduce ( inval, retval , 1, MPI_INTEGER, MPI_BXOR, local_communicator, ierr )
  1074. wrf_dm_bxor_integer = retval
  1075. #else
  1076. INTEGER inval
  1077. wrf_dm_bxor_integer = inval
  1078. #endif
  1079. END FUNCTION wrf_dm_bxor_integer
  1080. SUBROUTINE wrf_dm_maxval_real ( val, idex, jdex )
  1081. IMPLICIT NONE
  1082. #ifndef STUBMPI
  1083. INCLUDE 'mpif.h'
  1084. REAL val, val_all( ntasks )
  1085. INTEGER idex, jdex, ierr
  1086. INTEGER dex(2)
  1087. INTEGER dex_all (2,ntasks)
  1088. INTEGER i
  1089. dex(1) = idex ; dex(2) = jdex
  1090. CALL mpi_allgather ( dex, 2, MPI_INTEGER, dex_all , 2, MPI_INTEGER, local_communicator, ierr )
  1091. CALL mpi_allgather ( val, 1, getrealmpitype(), val_all , 1, getrealmpitype(), local_communicator, ierr )
  1092. val = val_all(1)
  1093. idex = dex_all(1,1) ; jdex = dex_all(2,1)
  1094. DO i = 2, ntasks
  1095. IF ( val_all(i) .GT. val ) THEN
  1096. val = val_all(i)
  1097. idex = dex_all(1,i)
  1098. jdex = dex_all(2,i)
  1099. ENDIF
  1100. ENDDO
  1101. #else
  1102. REAL val
  1103. INTEGER idex, jdex, ierr
  1104. #endif
  1105. END SUBROUTINE wrf_dm_maxval_real
  1106. #ifndef PROMOTE_FLOAT
  1107. SUBROUTINE wrf_dm_maxval_doubleprecision ( val, idex, jdex )
  1108. IMPLICIT NONE
  1109. # ifndef STUBMPI
  1110. INCLUDE 'mpif.h'
  1111. DOUBLE PRECISION val, val_all( ntasks )
  1112. INTEGER idex, jdex, ierr
  1113. INTEGER dex(2)
  1114. INTEGER dex_all (2,ntasks)
  1115. INTEGER i
  1116. dex(1) = idex ; dex(2) = jdex
  1117. CALL mpi_allgather ( dex, 2, MPI_INTEGER, dex_all , 2, MPI_INTEGER, local_communicator, ierr )
  1118. CALL mpi_allgather ( val, 1, MPI_DOUBLE_PRECISION, val_all , 1, MPI_DOUBLE_PRECISION, local_communicator, ierr )
  1119. val = val_all(1)
  1120. idex = dex_all(1,1) ; jdex = dex_all(2,1)
  1121. DO i = 2, ntasks
  1122. IF ( val_all(i) .GT. val ) THEN
  1123. val = val_all(i)
  1124. idex = dex_all(1,i)
  1125. jdex = dex_all(2,i)
  1126. ENDIF
  1127. ENDDO
  1128. # else
  1129. DOUBLE PRECISION val
  1130. INTEGER idex, jdex, ierr
  1131. # endif
  1132. END SUBROUTINE wrf_dm_maxval_doubleprecision
  1133. #endif
  1134. SUBROUTINE wrf_dm_maxval_integer ( val, idex, jdex )
  1135. IMPLICIT NONE
  1136. #ifndef STUBMPI
  1137. INCLUDE 'mpif.h'
  1138. INTEGER val, val_all( ntasks )
  1139. INTEGER idex, jdex, ierr
  1140. INTEGER dex(2)
  1141. INTEGER dex_all (2,ntasks)
  1142. INTEGER i
  1143. dex(1) = idex ; dex(2) = jdex
  1144. CALL mpi_allgather ( dex, 2, MPI_INTEGER, dex_all , 2, MPI_INTEGER, local_communicator, ierr )
  1145. CALL mpi_allgather ( val, 1, MPI_INTEGER, val_all , 1, MPI_INTEGER, local_communicator, ierr )
  1146. val = val_all(1)
  1147. idex = dex_all(1,1) ; jdex = dex_all(2,1)
  1148. DO i = 2, ntasks
  1149. IF ( val_all(i) .GT. val ) THEN
  1150. val = val_all(i)
  1151. idex = dex_all(1,i)
  1152. jdex = dex_all(2,i)
  1153. ENDIF
  1154. ENDDO
  1155. #else
  1156. INTEGER val
  1157. INTEGER idex, jdex
  1158. #endif
  1159. END SUBROUTINE wrf_dm_maxval_integer
  1160. ! For HWRF some additional computation is required. This is gopal's doing
  1161. SUBROUTINE wrf_dm_minval_real ( val, idex, jdex )
  1162. IMPLICIT NONE
  1163. REAL val, val_all( ntasks )
  1164. INTEGER idex, jdex, ierr
  1165. INTEGER dex(2)
  1166. INTEGER dex_all (2,ntasks)
  1167. ! <DESCRIPTION>
  1168. ! Collective operation. Each processor calls passing a local value and its index; on return
  1169. ! all processors are passed back the maximum of all values passed and its index.
  1170. !
  1171. ! </DESCRIPTION>
  1172. INTEGER i, comm
  1173. #ifndef STUBMPI
  1174. INCLUDE 'mpif.h'
  1175. CALL wrf_get_dm_communicator ( comm )
  1176. dex(1) = idex ; dex(2) = jdex
  1177. CALL mpi_allgather ( dex, 2, MPI_INTEGER, dex_all , 2, MPI_INTEGER, comm, ierr )
  1178. CALL mpi_allgather ( val, 1, MPI_REAL, val_all , 1, MPI_REAL, comm, ierr )
  1179. val = val_all(1)
  1180. idex = dex_all(1,1) ; jdex = dex_all(2,1)
  1181. DO i = 2, ntasks
  1182. IF ( val_all(i) .LT. val ) THEN
  1183. val = val_all(i)
  1184. idex = dex_all(1,i)
  1185. jdex = dex_all(2,i)
  1186. ENDIF
  1187. ENDDO
  1188. #endif
  1189. END SUBROUTINE wrf_dm_minval_real
  1190. #ifndef PROMOTE_FLOAT
  1191. SUBROUTINE wrf_dm_minval_doubleprecision ( val, idex, jdex )
  1192. IMPLICIT NONE
  1193. DOUBLE PRECISION val, val_all( ntasks )
  1194. INTEGER idex, jdex, ierr
  1195. INTEGER dex(2)
  1196. INTEGER dex_all (2,ntasks)
  1197. ! <DESCRIPTION>
  1198. ! Collective operation. Each processor calls passing a local value and its index; on return
  1199. ! all processors are passed back the maximum of all values passed and its index.
  1200. !
  1201. ! </DESCRIPTION>
  1202. INTEGER i, comm
  1203. #ifndef STUBMPI
  1204. INCLUDE 'mpif.h'
  1205. CALL wrf_get_dm_communicator ( comm )
  1206. dex(1) = idex ; dex(2) = jdex
  1207. CALL mpi_allgather ( dex, 2, MPI_INTEGER, dex_all , 2, MPI_INTEGER, comm, ierr )
  1208. CALL mpi_allgather ( val, 1, MPI_DOUBLE_PRECISION, val_all , 1, MPI_DOUBLE_PRECISION, comm, ierr )
  1209. val = val_all(1)
  1210. idex = dex_all(1,1) ; jdex = dex_all(2,1)
  1211. DO i = 2, ntasks
  1212. IF ( val_all(i) .LT. val ) THEN
  1213. val = val_all(i)
  1214. idex = dex_all(1,i)
  1215. jdex = dex_all(2,i)
  1216. ENDIF
  1217. ENDDO
  1218. #endif
  1219. END SUBROUTINE wrf_dm_minval_doubleprecision
  1220. #endif
  1221. SUBROUTINE wrf_dm_minval_integer ( val, idex, jdex )
  1222. IMPLICIT NONE
  1223. INTEGER val, val_all( ntasks )
  1224. INTEGER idex, jdex, ierr
  1225. INTEGER dex(2)
  1226. INTEGER dex_all (2,ntasks)
  1227. ! <DESCRIPTION>
  1228. ! Collective operation. Each processor calls passing a local value and its index; on return
  1229. ! all processors are passed back the maximum of all values passed and its index.
  1230. !
  1231. ! </DESCRIPTION>
  1232. INTEGER i, comm
  1233. #ifndef STUBMPI
  1234. INCLUDE 'mpif.h'
  1235. CALL wrf_get_dm_communicator ( comm )
  1236. dex(1) = idex ; dex(2) = jdex
  1237. CALL mpi_allgather ( dex, 2, MPI_INTEGER, dex_all , 2, MPI_INTEGER, comm, ierr )
  1238. CALL mpi_allgather ( val, 1, MPI_INTEGER, val_all , 1, MPI_INTEGER, comm, ierr )
  1239. val = val_all(1)
  1240. idex = dex_all(1,1) ; jdex = dex_all(2,1)
  1241. DO i = 2, ntasks
  1242. IF ( val_all(i) .LT. val ) THEN
  1243. val = val_all(i)
  1244. idex = dex_all(1,i)
  1245. jdex = dex_all(2,i)
  1246. ENDIF
  1247. ENDDO
  1248. #endif
  1249. END SUBROUTINE wrf_dm_minval_integer ! End of gopal's doing
  1250. SUBROUTINE split_communicator
  1251. #ifndef STUBMPI
  1252. IMPLICIT NONE
  1253. INCLUDE 'mpif.h'
  1254. LOGICAL mpi_inited
  1255. INTEGER mpi_comm_here, mpi_comm_local, comdup, mytask, ntasks, ierr, io_status
  1256. # if defined(_OPENMP) && defined(MPI2_THREAD_SUPPORT)
  1257. INTEGER thread_support_provided, thread_support_requested
  1258. #endif
  1259. INTEGER i, j
  1260. INTEGER, ALLOCATABLE :: icolor(:)
  1261. INTEGER tasks_per_split
  1262. NAMELIST /namelist_split/ tasks_per_split
  1263. CALL MPI_INITIALIZED( mpi_inited, ierr )
  1264. IF ( .NOT. mpi_inited ) THEN
  1265. # if defined(_OPENMP) && defined(MPI2_THREAD_SUPPORT)
  1266. thread_support_requested = MPI_THREAD_FUNNELED
  1267. CALL mpi_init_thread ( thread_support_requested, thread_support_provided, ierr )
  1268. IF ( thread_support_provided .lt. thread_support_requested ) THEN
  1269. CALL WRF_ERROR_FATAL( "failed to initialize MPI thread support")
  1270. ENDIF
  1271. # else
  1272. CALL mpi_init ( ierr )
  1273. # endif
  1274. mpi_comm_here = MPI_COMM_WORLD
  1275. #ifdef HWRF
  1276. CALL atm_cmp_start( mpi_comm_here ) ! atmospheric side of HWRF coupler will split MPI_COMM_WORLD and return communicator as argument
  1277. #endif
  1278. CALL wrf_set_dm_communicator( mpi_comm_here )
  1279. ENDIF
  1280. CALL wrf_get_dm_communicator( mpi_comm_here )
  1281. CALL wrf_termio_dup( mpi_comm_here )
  1282. CALL MPI_Comm_rank ( mpi_comm_here, mytask, ierr ) ;
  1283. CALL mpi_comm_size ( mpi_comm_here, ntasks, ierr ) ;
  1284. IF ( mytask .EQ. 0 ) THEN
  1285. OPEN ( unit=27, file="namelist.input", form="formatted", status="old" )
  1286. tasks_per_split = ntasks
  1287. READ ( 27 , NML = namelist_split, IOSTAT=io_status )
  1288. CLOSE ( 27 )
  1289. ENDIF
  1290. CALL mpi_bcast( io_status, 1 , MPI_INTEGER , 0 , mpi_comm_here, ierr )
  1291. IF ( io_status .NE. 0 ) THEN
  1292. RETURN ! just ignore and return
  1293. ENDIF
  1294. CALL mpi_bcast( tasks_per_split, 1 , MPI_INTEGER , 0 , mpi_comm_here, ierr )
  1295. IF ( tasks_per_split .GT. ntasks .OR. tasks_per_split .LE. 0 ) RETURN
  1296. IF ( mod( ntasks, tasks_per_split ) .NE. 0 ) THEN
  1297. CALL wrf_message( 'WARNING: tasks_per_split does not evenly divide ntasks. Some tasks will be wasted.' )
  1298. ENDIF
  1299. ALLOCATE( icolor(ntasks) )
  1300. j = 0
  1301. DO WHILE ( j .LT. ntasks / tasks_per_split )
  1302. DO i = 1, tasks_per_split
  1303. icolor( i + j * tasks_per_split ) = j
  1304. ENDDO
  1305. j = j + 1
  1306. ENDDO
  1307. CALL MPI_Comm_dup(mpi_comm_here,comdup,ierr)
  1308. CALL MPI_Comm_split(comdup,icolor(mytask+1),mytask,mpi_comm_local,ierr)
  1309. CALL wrf_set_dm_communicator( mpi_comm_local )
  1310. DEALLOCATE( icolor )
  1311. #endif
  1312. END SUBROUTINE split_communicator
  1313. SUBROUTINE init_module_dm
  1314. #ifndef STUBMPI
  1315. IMPLICIT NONE
  1316. INTEGER mpi_comm_local, mpi_comm_here, ierr, mytask, nproc
  1317. INCLUDE 'mpif.h'
  1318. LOGICAL mpi_inited
  1319. CALL mpi_initialized( mpi_inited, ierr )
  1320. IF ( .NOT. mpi_inited ) THEN
  1321. ! If MPI has not been initialized then initialize it and
  1322. ! make comm_world the communicator
  1323. ! Otherwise, something else (e.g. split_communicator) has already
  1324. ! initialized MPI, so just grab the communicator that
  1325. ! should already be stored and use that.
  1326. CALL mpi_init ( ierr )
  1327. mpi_comm_here = MPI_COMM_WORLD
  1328. CALL wrf_set_dm_communicator ( mpi_comm_here )
  1329. ENDIF
  1330. CALL wrf_get_dm_communicator( mpi_comm_local )
  1331. CALL wrf_termio_dup( mpi_comm_local )
  1332. #endif
  1333. END SUBROUTINE init_module_dm
  1334. ! stub
  1335. SUBROUTINE wrf_dm_move_nest ( parent, nest, dx, dy )
  1336. USE module_domain, ONLY : domain
  1337. IMPLICIT NONE
  1338. TYPE (domain), INTENT(INOUT) :: parent, nest
  1339. INTEGER, INTENT(IN) :: dx,dy
  1340. RETURN
  1341. END SUBROUTINE wrf_dm_move_nest
  1342. !------------------------------------------------------------------------------
  1343. SUBROUTINE get_full_obs_vector( nsta, nerrf, niobf, &
  1344. mp_local_uobmask, &
  1345. mp_local_vobmask, &
  1346. mp_local_cobmask, errf )
  1347. !------------------------------------------------------------------------------
  1348. ! PURPOSE: Do MPI allgatherv operation across processors to get the
  1349. ! errors at each observation point on all processors.
  1350. !
  1351. !------------------------------------------------------------------------------
  1352. INTEGER, INTENT(IN) :: nsta ! Observation index.
  1353. INTEGER, INTENT(IN) :: nerrf ! Number of error fields.
  1354. INTEGER, INTENT(IN) :: niobf ! Number of observations.
  1355. LOGICAL, INTENT(IN) :: MP_LOCAL_UOBMASK(NIOBF)
  1356. LOGICAL, INTENT(IN) :: MP_LOCAL_VOBMASK(NIOBF)
  1357. LOGICAL, INTENT(IN) :: MP_LOCAL_COBMASK(NIOBF)
  1358. REAL, INTENT(INOUT) :: errf(nerrf, niobf)
  1359. #ifndef STUBMPI
  1360. INCLUDE 'mpif.h'
  1361. ! Local declarations
  1362. integer i, n, nlocal_dot, nlocal_crs
  1363. REAL UVT_BUFFER(NIOBF) ! Buffer for holding U, V, or T
  1364. REAL QRK_BUFFER(NIOBF) ! Buffer for holding Q or RKO
  1365. REAL SFP_BUFFER(NIOBF) ! Buffer for holding Surface pressure
  1366. REAL PBL_BUFFER(NIOBF) ! Buffer for holding (real) KPBL index
  1367. INTEGER N_BUFFER(NIOBF)
  1368. REAL FULL_BUFFER(NIOBF)
  1369. INTEGER IFULL_BUFFER(NIOBF)
  1370. INTEGER IDISPLACEMENT(1024) ! HARD CODED MAX NUMBER OF PROCESSORS
  1371. INTEGER ICOUNT(1024) ! HARD CODED MAX NUMBER OF PROCESSORS
  1372. INTEGER :: MPI_COMM_COMP ! MPI group communicator
  1373. INTEGER :: NPROCS ! Number of processors
  1374. INTEGER :: IERR ! Error code from MPI routines
  1375. ! Get communicator for MPI operations.
  1376. CALL WRF_GET_DM_COMMUNICATOR(MPI_COMM_COMP)
  1377. ! Get rank of monitor processor and broadcast to others.
  1378. CALL MPI_COMM_SIZE( MPI_COMM_COMP, NPROCS, IERR )
  1379. ! DO THE U FIELD
  1380. NLOCAL_DOT = 0
  1381. DO N = 1, NSTA
  1382. IF ( MP_LOCAL_UOBMASK(N) ) THEN ! USE U-POINT MASK
  1383. NLOCAL_DOT = NLOCAL_DOT + 1
  1384. UVT_BUFFER(NLOCAL_DOT) = ERRF(1,N) ! U WIND COMPONENT
  1385. SFP_BUFFER(NLOCAL_DOT) = ERRF(7,N) ! SURFACE PRESSURE
  1386. QRK_BUFFER(NLOCAL_DOT) = ERRF(9,N) ! RKO
  1387. N_BUFFER(NLOCAL_DOT) = N
  1388. ENDIF
  1389. ENDDO
  1390. CALL MPI_ALLGATHER(NLOCAL_DOT,1,MPI_INTEGER, &
  1391. ICOUNT,1,MPI_INTEGER, &
  1392. MPI_COMM_COMP,IERR)
  1393. I = 1
  1394. IDISPLACEMENT(1) = 0
  1395. DO I = 2, NPROCS
  1396. IDISPLACEMENT(I) = IDISPLACEMENT(I-1) + ICOUNT(I-1)
  1397. ENDDO
  1398. CALL MPI_ALLGATHERV( N_BUFFER, NLOCAL_DOT, MPI_INTEGER, &
  1399. IFULL_BUFFER, ICOUNT, IDISPLACEMENT, &
  1400. MPI_INTEGER, MPI_COMM_COMP, IERR)
  1401. ! U
  1402. CALL MPI_ALLGATHERV( UVT_BUFFER, NLOCAL_DOT, MPI_REAL, &
  1403. FULL_BUFFER, ICOUNT, IDISPLACEMENT, &
  1404. MPI_REAL, MPI_COMM_COMP, IERR)
  1405. DO N = 1, NSTA
  1406. ERRF(1,IFULL_BUFFER(N)) = FULL_BUFFER(N)
  1407. ENDDO
  1408. ! SURF PRESS AT U-POINTS
  1409. CALL MPI_ALLGATHERV( SFP_BUFFER, NLOCAL_DOT, MPI_REAL, &
  1410. FULL_BUFFER, ICOUNT, IDISPLACEMENT, &
  1411. MPI_REAL, MPI_COMM_COMP, IERR)
  1412. DO N = 1, NSTA
  1413. ERRF(7,IFULL_BUFFER(N)) = FULL_BUFFER(N)
  1414. ENDDO
  1415. ! RKO
  1416. CALL MPI_ALLGATHERV( QRK_BUFFER, NLOCAL_DOT, MPI_REAL, &
  1417. FULL_BUFFER, ICOUNT, IDISPLACEMENT, &
  1418. MPI_REAL, MPI_COMM_COMP, IERR)
  1419. DO N = 1, NSTA
  1420. ERRF(9,IFULL_BUFFER(N)) = FULL_BUFFER(N)
  1421. ENDDO
  1422. ! DO THE V FIELD
  1423. NLOCAL_DOT = 0
  1424. DO N = 1, NSTA
  1425. IF ( MP_LOCAL_VOBMASK(N) ) THEN ! USE V-POINT MASK
  1426. NLOCAL_DOT = NLOCAL_DOT + 1
  1427. UVT_BUFFER(NLOCAL_DOT) = ERRF(2,N) ! V WIND COMPONENT
  1428. SFP_BUFFER(NLOCAL_DOT) = ERRF(8,N) ! SURFACE PRESSURE
  1429. N_BUFFER(NLOCAL_DOT) = N
  1430. ENDIF
  1431. ENDDO
  1432. CALL MPI_ALLGATHER(NLOCAL_DOT,1,MPI_INTEGER, &
  1433. ICOUNT,1,MPI_INTEGER, &
  1434. MPI_COMM_COMP,IERR)
  1435. I = 1
  1436. IDISPLACEMENT(1) = 0
  1437. DO I = 2, NPROCS
  1438. IDISPLACEMENT(I) = IDISPLACEMENT(I-1) + ICOUNT(I-1)
  1439. ENDDO
  1440. CALL MPI_ALLGATHERV( N_BUFFER, NLOCAL_DOT, MPI_INTEGER, &
  1441. IFULL_BUFFER, ICOUNT, IDISPLACEMENT, &
  1442. MPI_INTEGER, MPI_COMM_COMP, IERR)
  1443. ! V
  1444. CALL MPI_ALLGATHERV( UVT_BUFFER, NLOCAL_DOT, MPI_REAL, &
  1445. FULL_BUFFER, ICOUNT, IDISPLACEMENT, &
  1446. MPI_REAL, MPI_COMM_COMP, IERR)
  1447. DO N = 1, NSTA
  1448. ERRF(2,IFULL_BUFFER(N)) = FULL_BUFFER(N)
  1449. ENDDO
  1450. ! SURF PRESS AT V-POINTS
  1451. CALL MPI_ALLGATHERV( SFP_BUFFER, NLOCAL_DOT, MPI_REAL, &
  1452. FULL_BUFFER, ICOUNT, IDISPLACEMENT, &
  1453. MPI_REAL, MPI_COMM_COMP, IERR)
  1454. DO N = 1, NSTA
  1455. ERRF(8,IFULL_BUFFER(N)) = FULL_BUFFER(N)
  1456. ENDDO
  1457. ! DO THE CROSS FIELDS, T AND Q
  1458. NLOCAL_CRS = 0
  1459. DO N = 1, NSTA
  1460. IF ( MP_LOCAL_COBMASK(N) ) THEN ! USE MASS-POINT MASK
  1461. NLOCAL_CRS = NLOCAL_CRS + 1
  1462. UVT_BUFFER(NLOCAL_CRS) = ERRF(3,N) ! TEMPERATURE
  1463. QRK_BUFFER(NLOCAL_CRS) = ERRF(4,N) ! MOISTURE
  1464. PBL_BUFFER(NLOCAL_CRS) = ERRF(5,N) ! KPBL
  1465. SFP_BUFFER(NLOCAL_CRS) = ERRF(6,N) ! SURFACE PRESSURE
  1466. N_BUFFER(NLOCAL_CRS) = N
  1467. ENDIF
  1468. ENDDO
  1469. CALL MPI_ALLGATHER(NLOCAL_CRS,1,MPI_INTEGER, &
  1470. ICOUNT,1,MPI_INTEGER, &
  1471. MPI_COMM_COMP,IERR)
  1472. IDISPLACEMENT(1) = 0
  1473. DO I = 2, NPROCS
  1474. IDISPLACEMENT(I) = IDISPLACEMENT(I-1) + ICOUNT(I-1)
  1475. ENDDO
  1476. CALL MPI_ALLGATHERV( N_BUFFER, NLOCAL_CRS, MPI_INTEGER, &
  1477. IFULL_BUFFER, ICOUNT, IDISPLACEMENT, &
  1478. MPI_INTEGER, MPI_COMM_COMP, IERR)
  1479. ! T
  1480. CALL MPI_ALLGATHERV( UVT_BUFFER, NLOCAL_CRS, MPI_REAL, &
  1481. FULL_BUFFER, ICOUNT, IDISPLACEMENT, &
  1482. MPI_REAL, MPI_COMM_COMP, IERR)
  1483. DO N = 1, NSTA
  1484. ERRF(3,IFULL_BUFFER(N)) = FULL_BUFFER(N)
  1485. ENDDO
  1486. ! Q
  1487. CALL MPI_ALLGATHERV( QRK_BUFFER, NLOCAL_CRS, MPI_REAL, &
  1488. FULL_BUFFER, ICOUNT, IDISPLACEMENT, &
  1489. MPI_REAL, MPI_COMM_COMP, IERR)
  1490. DO N = 1, NSTA
  1491. ERRF(4,IFULL_BUFFER(N)) = FULL_BUFFER(N)
  1492. ENDDO
  1493. ! KPBL
  1494. CALL MPI_ALLGATHERV( PBL_BUFFER, NLOCAL_CRS, MPI_REAL, &
  1495. FULL_BUFFER, ICOUNT, IDISPLACEMENT, &
  1496. MPI_REAL, MPI_COMM_COMP, IERR)
  1497. DO N = 1, NSTA
  1498. ERRF(5,IFULL_BUFFER(N)) = FULL_BUFFER(N)
  1499. ENDDO
  1500. ! SURF PRESS AT MASS POINTS
  1501. CALL MPI_ALLGATHERV( SFP_BUFFER, NLOCAL_CRS, MPI_REAL, &
  1502. FULL_BUFFER, ICOUNT, IDISPLACEMENT, &
  1503. MPI_REAL, MPI_COMM_COMP, IERR)
  1504. DO N = 1, NSTA
  1505. ERRF(6,IFULL_BUFFER(N)) = FULL_BUFFER(N)
  1506. ENDDO
  1507. #endif
  1508. END SUBROUTINE get_full_obs_vector
  1509. SUBROUTINE wrf_dm_maxtile_real ( val , tile)
  1510. IMPLICIT NONE
  1511. REAL val, val_all( ntasks )
  1512. INTEGER tile
  1513. INTEGER ierr
  1514. ! <DESCRIPTION>
  1515. ! Collective operation. Each processor calls passing a local value and its index; on return
  1516. ! all processors are passed back the maximum of all values passed and its tile number.
  1517. !
  1518. ! </DESCRIPTION>
  1519. INTEGER i, comm
  1520. #ifndef STUBMPI
  1521. INCLUDE 'mpif.h'
  1522. CALL wrf_get_dm_communicator ( comm )
  1523. CALL mpi_allgather ( val, 1, getrealmpitype(), val_all , 1, getrealmpitype(), comm, ierr )
  1524. val = val_all(1)
  1525. tile = 1
  1526. DO i = 2, ntasks
  1527. IF ( val_all(i) .GT. val ) THEN
  1528. tile = i
  1529. val = val_all(i)
  1530. ENDIF
  1531. ENDDO
  1532. #endif
  1533. END SUBROUTINE wrf_dm_maxtile_real
  1534. SUBROUTINE wrf_dm_mintile_real ( val , tile)
  1535. IMPLICIT NONE
  1536. REAL val, val_all( ntasks )
  1537. INTEGER tile
  1538. INTEGER ierr
  1539. ! <DESCRIPTION>
  1540. ! Collective operation. Each processor calls passing a local value and its index; on return
  1541. ! all processors are passed back the minimum of all values passed and its tile number.
  1542. !
  1543. ! </DESCRIPTION>
  1544. INTEGER i, comm
  1545. #ifndef STUBMPI
  1546. INCLUDE 'mpif.h'
  1547. CALL wrf_get_dm_communicator ( comm )
  1548. CALL mpi_allgather ( val, 1, getrealmpitype(), val_all , 1, getrealmpitype(), comm, ierr )
  1549. val = val_all(1)
  1550. tile = 1
  1551. DO i = 2, ntasks
  1552. IF ( val_all(i) .LT. val ) THEN
  1553. tile = i
  1554. val = val_all(i)
  1555. ENDIF
  1556. ENDDO
  1557. #endif
  1558. END SUBROUTINE wrf_dm_mintile_real
  1559. SUBROUTINE wrf_dm_mintile_double ( val , tile)
  1560. IMPLICIT NONE
  1561. DOUBLE PRECISION val, val_all( ntasks )
  1562. INTEGER tile
  1563. INTEGER ierr
  1564. ! <DESCRIPTION>
  1565. ! Collective operation. Each processor calls passing a local value and its index; on return
  1566. ! all processors are passed back the minimum of all values passed and its tile number.
  1567. !
  1568. ! </DESCRIPTION>
  1569. INTEGER i, comm
  1570. #ifndef STUBMPI
  1571. INCLUDE 'mpif.h'
  1572. CALL wrf_get_dm_communicator ( comm )
  1573. CALL mpi_allgather ( val, 1, MPI_DOUBLE_PRECISION, val_all , 1, MPI_DOUBLE_PRECISION, comm, ierr )
  1574. val = val_all(1)
  1575. tile = 1
  1576. DO i = 2, ntasks
  1577. IF ( val_all(i) .LT. val ) THEN
  1578. tile = i
  1579. val = val_all(i)
  1580. ENDIF
  1581. ENDDO
  1582. #endif
  1583. END SUBROUTINE wrf_dm_mintile_double
  1584. SUBROUTINE wrf_dm_tile_val_int ( val , tile)
  1585. IMPLICIT NONE
  1586. INTEGER val, val_all( ntasks )
  1587. INTEGER tile
  1588. INTEGER ierr
  1589. ! <DESCRIPTION>
  1590. ! Collective operation. Get value from input tile.
  1591. !
  1592. ! </DESCRIPTION>
  1593. INTEGER i, comm
  1594. #ifndef STUBMPI
  1595. INCLUDE 'mpif.h'
  1596. CALL wrf_get_dm_communicator ( comm )
  1597. CALL mpi_allgather ( val, 1, MPI_INTEGER, val_all , 1, MPI_INTEGER, comm, ierr )
  1598. val = val_all(tile)
  1599. #endif
  1600. END SUBROUTINE wrf_dm_tile_val_int
  1601. SUBROUTINE wrf_get_hostname ( str )
  1602. CHARACTER*(*) str
  1603. CHARACTER tmp(512)
  1604. INTEGER i , n, cs
  1605. CALL rsl_lite_get_hostname( tmp, 512, n, cs )
  1606. DO i = 1, n
  1607. str(i:i) = tmp(i)
  1608. ENDDO
  1609. RETURN
  1610. END SUBROUTINE wrf_get_hostname
  1611. SUBROUTINE wrf_get_hostid ( hostid )
  1612. INTEGER hostid
  1613. CHARACTER tmp(512)
  1614. INTEGER i, sz, n, cs
  1615. CALL rsl_lite_get_hostname( tmp, 512, n, cs )
  1616. hostid = cs
  1617. RETURN
  1618. END SUBROUTINE wrf_get_hostid
  1619. END MODULE module_dm
  1620. !=========================================================================
  1621. ! wrf_dm_patch_domain has to be outside the module because it is called
  1622. ! by a routine in module_domain but depends on module domain
  1623. SUBROUTINE wrf_dm_patch_domain ( id , domdesc , parent_id , parent_domdesc , &
  1624. sd1 , ed1 , sp1 , ep1 , sm1 , em1 , &
  1625. sd2 , ed2 , sp2 , ep2 , sm2 , em2 , &
  1626. sd3 , ed3 , sp3 , ep3 , sm3 , em3 , &
  1627. sp1x , ep1x , sm1x , em1x , &
  1628. sp2x , ep2x , sm2x , em2x , &
  1629. sp3x , ep3x , sm3x , em3x , &
  1630. sp1y , ep1y , sm1y , em1y , &
  1631. sp2y , ep2y , sm2y , em2y , &
  1632. sp3y , ep3y , sm3y , em3y , &
  1633. bdx , bdy )
  1634. USE module_domain, ONLY : domain, head_grid, find_grid_by_id
  1635. USE module_dm, ONLY : patch_domain_rsl_lite
  1636. IMPLICIT NONE
  1637. INTEGER, INTENT(IN) :: sd1 , ed1 , sd2 , ed2 , sd3 , ed3 , bdx , bdy
  1638. INTEGER, INTENT(OUT) :: sp1 , ep1 , sp2 , ep2 , sp3 , ep3 , &
  1639. sm1 , em1 , sm2 , em2 , sm3 , em3
  1640. INTEGER :: sp1x , ep1x , sp2x , ep2x , sp3x , ep3x , &
  1641. sm1x , em1x , sm2x , em2x , sm3x , em3x
  1642. INTEGER :: sp1y , ep1y , sp2y , ep2y , sp3y , ep3y , &
  1643. sm1y , em1y , sm2y , em2y , sm3y , em3y
  1644. INTEGER, INTENT(INOUT):: id , domdesc , parent_id , parent_domdesc
  1645. TYPE(domain), POINTER :: parent
  1646. TYPE(domain), POINTER :: grid_ptr
  1647. ! this is necessary because we cannot pass parent directly into
  1648. ! wrf_dm_patch_domain because creating the correct interface definitions
  1649. ! would generate a circular USE reference between module_domain and module_dm
  1650. ! see comment this date in module_domain for more information. JM 20020416
  1651. NULLIFY( parent )
  1652. grid_ptr => head_grid
  1653. CALL find_grid_by_id( parent_id , grid_ptr , parent )
  1654. CALL patch_domain_rsl_lite ( id , parent, parent_id , &
  1655. sd1 , ed1 , sp1 , ep1 , sm1 , em1 , &
  1656. sd2 , ed2 , sp2 , ep2 , sm2 , em2 , &
  1657. sd3 , ed3 , sp3 , ep3 , sm3 , em3 , &
  1658. sp1x , ep1x , sm1x , em1x , &
  1659. sp2x , ep2x , sm2x , em2x , &
  1660. sp3x , ep3x , sm3x , em3x , &
  1661. sp1y , ep1y , sm1y , em1y , &
  1662. sp2y , ep2y , sm2y , em2y , &
  1663. sp3y , ep3y , sm3y , em3y , &
  1664. bdx , bdy )
  1665. RETURN
  1666. END SUBROUTINE wrf_dm_patch_domain
  1667. SUBROUTINE wrf_termio_dup( comm )
  1668. IMPLICIT NONE
  1669. INTEGER, INTENT(IN) :: comm
  1670. INTEGER mytask, ntasks
  1671. #ifndef STUBMPI
  1672. INTEGER ierr
  1673. INCLUDE 'mpif.h'
  1674. CALL mpi_comm_size(comm, ntasks, ierr )
  1675. CALL mpi_comm_rank(comm, mytask, ierr )
  1676. write(0,*)'starting wrf task ',mytask,' of ',ntasks
  1677. CALL rsl_error_dup1( mytask )
  1678. #else
  1679. mytask = 0
  1680. ntasks = 1
  1681. #endif
  1682. END SUBROUTINE wrf_termio_dup
  1683. SUBROUTINE wrf_get_myproc( myproc )
  1684. USE module_dm , ONLY : mytask
  1685. IMPLICIT NONE
  1686. INTEGER myproc
  1687. myproc = mytask
  1688. RETURN
  1689. END SUBROUTINE wrf_get_myproc
  1690. SUBROUTINE wrf_get_nproc( nproc )
  1691. USE module_dm , ONLY : ntasks
  1692. IMPLICIT NONE
  1693. INTEGER nproc
  1694. nproc = ntasks
  1695. RETURN
  1696. END SUBROUTINE wrf_get_nproc
  1697. SUBROUTINE wrf_get_nprocx( nprocx )
  1698. USE module_dm , ONLY : ntasks_x
  1699. IMPLICIT NONE
  1700. INTEGER nprocx
  1701. nprocx = ntasks_x
  1702. RETURN
  1703. END SUBROUTINE wrf_get_nprocx
  1704. SUBROUTINE wrf_get_nprocy( nprocy )
  1705. USE module_dm , ONLY : ntasks_y
  1706. IMPLICIT NONE
  1707. INTEGER nprocy
  1708. nprocy = ntasks_y
  1709. RETURN
  1710. END SUBROUTINE wrf_get_nprocy
  1711. SUBROUTINE wrf_dm_bcast_bytes ( buf , size )
  1712. USE module_dm , ONLY : local_communicator
  1713. IMPLICIT NONE
  1714. #ifndef STUBMPI
  1715. INCLUDE 'mpif.h'
  1716. #endif
  1717. INTEGER size
  1718. #ifndef NEC
  1719. INTEGER*1 BUF(size)
  1720. #else
  1721. CHARACTER*1 BUF(size)
  1722. #endif
  1723. #ifndef STUBMPI
  1724. CALL BYTE_BCAST ( buf , size, local_communicator )
  1725. #endif
  1726. RETURN
  1727. END SUBROUTINE wrf_dm_bcast_bytes
  1728. SUBROUTINE wrf_dm_bcast_string( BUF, N1 )
  1729. IMPLICIT NONE
  1730. INTEGER n1
  1731. ! <DESCRIPTION>
  1732. ! Collective operation. Given a string and a size in characters on task zero, broadcast and return that buffer on all tasks.
  1733. !
  1734. ! </DESCRIPTION>
  1735. CHARACTER*(*) buf
  1736. #ifndef STUBMPI
  1737. INTEGER ibuf(256),i,n
  1738. CHARACTER*256 tstr
  1739. n = n1
  1740. ! Root task is required to have the correct value of N1, other tasks
  1741. ! might not have the correct value.
  1742. CALL wrf_dm_bcast_integer( n , 1 )
  1743. IF (n .GT. 256) n = 256
  1744. IF (n .GT. 0 ) then
  1745. DO i = 1, n
  1746. ibuf(I) = ichar(buf(I:I))
  1747. ENDDO
  1748. CALL wrf_dm_bcast_integer( ibuf, n )
  1749. buf = ''
  1750. DO i = 1, n
  1751. buf(i:i) = char(ibuf(i))
  1752. ENDDO
  1753. ENDIF
  1754. #endif
  1755. RETURN
  1756. END SUBROUTINE wrf_dm_bcast_string
  1757. SUBROUTINE wrf_dm_bcast_integer( BUF, N1 )
  1758. IMPLICIT NONE
  1759. INTEGER n1
  1760. INTEGER buf(*)
  1761. CALL wrf_dm_bcast_bytes ( BUF , N1 * IWORDSIZE )
  1762. RETURN
  1763. END SUBROUTINE wrf_dm_bcast_integer
  1764. SUBROUTINE wrf_dm_bcast_double( BUF, N1 )
  1765. IMPLICIT NONE
  1766. INTEGER n1
  1767. ! this next declaration is REAL, not DOUBLE PRECISION because it will be autopromoted
  1768. ! to double precision by the compiler when WRF is compiled for 8 byte reals. Only reason
  1769. ! for having this separate routine is so we pass the correct MPI type to mpi_scatterv
  1770. ! since we were not indexing the globbuf and Field arrays it does not matter
  1771. REAL buf(*)
  1772. CALL wrf_dm_bcast_bytes ( BUF , N1 * DWORDSIZE )
  1773. RETURN
  1774. END SUBROUTINE wrf_dm_bcast_double
  1775. SUBROUTINE wrf_dm_bcast_real( BUF, N1 )
  1776. IMPLICIT NONE
  1777. INTEGER n1
  1778. REAL buf(*)
  1779. CALL wrf_dm_bcast_bytes ( BUF , N1 * RWORDSIZE )
  1780. RETURN
  1781. END SUBROUTINE wrf_dm_bcast_real
  1782. SUBROUTINE wrf_dm_bcast_logical( BUF, N1 )
  1783. IMPLICIT NONE
  1784. INTEGER n1
  1785. LOGICAL buf(*)
  1786. CALL wrf_dm_bcast_bytes ( BUF , N1 * LWORDSIZE )
  1787. RETURN
  1788. END SUBROUTINE wrf_dm_bcast_logical
  1789. SUBROUTINE write_68( grid, v , s , &
  1790. ids, ide, jds, jde, kds, kde, &
  1791. ims, ime, jms, jme, kms, kme, &
  1792. its, ite, jts, jte, kts, kte )
  1793. USE module_domain, ONLY : domain
  1794. IMPLICIT NONE
  1795. TYPE(domain) , INTENT (INOUT) :: grid
  1796. CHARACTER *(*) s
  1797. INTEGER ids, ide, jds, jde, kds, kde, &
  1798. ims, ime, jms, jme, kms, kme, &
  1799. its, ite, jts, jte, kts, kte
  1800. REAL, DIMENSION( ims:ime , kms:kme, jms:jme ) :: v
  1801. INTEGER i,j,k,ierr
  1802. logical, external :: wrf_dm_on_monitor
  1803. real globbuf( ids:ide, kds:kde, jds:jde )
  1804. character*3 ord, stag
  1805. if ( kds == kde ) then
  1806. ord = 'xy'
  1807. stag = 'xy'
  1808. CALL wrf_patch_to_global_real ( v, globbuf, grid%domdesc, stag, ord, &
  1809. ids, ide, jds, jde, kds, kde, &
  1810. ims, ime, jms, jme, kms, kme, &
  1811. its, ite, jts, jte, kts, kte )
  1812. else
  1813. stag = 'xyz'
  1814. ord = 'xzy'
  1815. CALL wrf_patch_to_global_real ( v, globbuf, grid%domdesc, stag, ord, &
  1816. ids, ide, kds, kde, jds, jde, &
  1817. ims, ime, kms, kme, jms, jme, &
  1818. its, ite, kts, kte, jts, jte )
  1819. endif
  1820. if ( wrf_dm_on_monitor() ) THEN
  1821. WRITE(68,*) ide-ids+1, jde-jds+1 , s
  1822. DO j = jds, jde
  1823. DO i = ids, ide
  1824. WRITE(68,*) globbuf(i,1,j)
  1825. ENDDO
  1826. ENDDO
  1827. endif
  1828. RETURN
  1829. END
  1830. SUBROUTINE wrf_abort
  1831. IMPLICIT NONE
  1832. #ifndef STUBMPI
  1833. INCLUDE 'mpif.h'
  1834. INTEGER ierr
  1835. CALL mpi_abort(MPI_COMM_WORLD,1,ierr)
  1836. #else
  1837. STOP
  1838. #endif
  1839. END SUBROUTINE wrf_abort
  1840. SUBROUTINE wrf_dm_shutdown
  1841. IMPLICIT NONE
  1842. #ifndef STUBMPI
  1843. INTEGER ierr
  1844. CALL MPI_FINALIZE( ierr )
  1845. #endif
  1846. RETURN
  1847. END SUBROUTINE wrf_dm_shutdown
  1848. LOGICAL FUNCTION wrf_dm_on_monitor()
  1849. IMPLICIT NONE
  1850. #ifndef STUBMPI
  1851. INCLUDE 'mpif.h'
  1852. INTEGER tsk, ierr, mpi_comm_local
  1853. CALL wrf_get_dm_communicator( mpi_comm_local )
  1854. CALL mpi_comm_rank ( mpi_comm_local, tsk , ierr )
  1855. wrf_dm_on_monitor = tsk .EQ. 0
  1856. #else
  1857. wrf_dm_on_monitor = .TRUE.
  1858. #endif
  1859. RETURN
  1860. END FUNCTION wrf_dm_on_monitor
  1861. SUBROUTINE rsl_comm_iter_init(shw,ps,pe)
  1862. INTEGER shw, ps, pe
  1863. INTEGER iter, plus_send_start, plus_recv_start, &
  1864. minus_send_start, minus_recv_start
  1865. COMMON /rcii/ iter, plus_send_start, plus_recv_start, &
  1866. minus_send_start, minus_recv_start
  1867. iter = 0
  1868. minus_send_start = ps
  1869. minus_recv_start = ps-1
  1870. plus_send_start = pe
  1871. plus_recv_start = pe+1
  1872. END SUBROUTINE rsl_comm_iter_init
  1873. LOGICAL FUNCTION rsl_comm_iter ( id , is_intermediate, &
  1874. shw , xy , ds, de_in, ps, pe, nds,nde, &
  1875. sendbeg_m, sendw_m, sendbeg_p, sendw_p, &
  1876. recvbeg_m, recvw_m, recvbeg_p, recvw_p )
  1877. USE module_dm, ONLY : ntasks_x, ntasks_y, mytask_x, mytask_y
  1878. IMPLICIT NONE
  1879. INTEGER, INTENT(IN) :: id,shw,xy,ds,de_in,ps,pe,nds,nde
  1880. LOGICAL, INTENT(IN) :: is_intermediate ! treated differently, coarse but with same decomp as nest
  1881. INTEGER, INTENT(OUT) :: sendbeg_m, sendw_m, sendbeg_p, sendw_p
  1882. INTEGER, INTENT(OUT) :: recvbeg_m, recvw_m, recvbeg_p, recvw_p
  1883. INTEGER k, kn, ni, nj, de, Px, Py, nt, me, lb, ub, ierr
  1884. LOGICAL went
  1885. INTEGER iter, plus_send_start, plus_recv_start, &
  1886. minus_send_start, minus_recv_start
  1887. INTEGER parent_grid_ratio, parent_start
  1888. COMMON /rcii/ iter, plus_send_start, plus_recv_start, &
  1889. minus_send_start, minus_recv_start
  1890. #if (NMM_CORE == 1 )
  1891. ! In case of NMM CORE, the domain only ever runs from ids..ide-1 and jds..jde-1 so
  1892. ! adjust decomposition to reflect. 20081206 JM
  1893. de = de_in - 1
  1894. #else
  1895. de = de_in
  1896. #endif
  1897. IF ( xy .EQ. 1 ) THEN ! X/I axis
  1898. nt = ntasks_x
  1899. me = mytask_x
  1900. IF ( is_intermediate ) THEN
  1901. CALL nl_get_i_parent_start(id,parent_start)
  1902. CALL nl_get_parent_grid_ratio(id,parent_grid_ratio)
  1903. ENDIF
  1904. ELSE
  1905. nt = ntasks_y
  1906. me = mytask_y
  1907. IF ( is_intermediate ) THEN
  1908. CALL nl_get_j_parent_start(id,parent_start)
  1909. CALL nl_get_parent_grid_ratio(id,parent_grid_ratio)
  1910. ENDIF
  1911. ENDIF
  1912. iter = iter + 1
  1913. #if (DA_CORE == 0)
  1914. went = .FALSE.
  1915. ! send to minus
  1916. sendw_m = 0
  1917. sendbeg_m = 1
  1918. IF ( me .GT. 0 ) THEN
  1919. lb = minus_send_start
  1920. sendbeg_m = lb-ps+1
  1921. DO k = lb,ps+shw-1
  1922. went = .TRUE.
  1923. IF ( is_intermediate ) THEN
  1924. kn = ( k - parent_start ) * parent_grid_ratio + 1 + 1 ;
  1925. CALL task_for_point (kn,1,nds,nde,1,1,nt,1,Px,Py,1,1,ierr) ! assume same alg. for x and y and just use x
  1926. ELSE
  1927. CALL task_for_point (k,1,ds,de,1,1,nt,1,Px,Py,1,1,ierr) ! assume same alg. for x and y and just use x
  1928. ENDIF
  1929. IF ( Px .NE. me+(iter-1) ) THEN
  1930. exit
  1931. ENDIF
  1932. minus_send_start = minus_send_start+1
  1933. sendw_m = sendw_m + 1
  1934. ENDDO
  1935. ENDIF
  1936. ! recv from minus
  1937. recvw_m = 0
  1938. recvbeg_m = 1
  1939. IF ( me .GT. 0 ) THEN
  1940. ub = minus_recv_start
  1941. recvbeg_m = ps - ub
  1942. DO k = minus_recv_start,ps-shw,-1
  1943. went = .TRUE.
  1944. IF ( is_intermediate ) THEN
  1945. kn = ( k - parent_start ) * parent_grid_ratio + 1 + 1 ;
  1946. CALL task_for_point (kn,1,nds,nde,1,1,nt,1,Px,Py,1,1,ierr) ! assume same alg. for x and y and just use x
  1947. ELSE
  1948. CALL task_for_point (k,1,ds,de,1,1,nt,1,Px,Py,1,1,ierr) ! assume same alg. for x and y and just use x
  1949. ENDIF
  1950. IF ( Px .NE. me-iter ) THEN
  1951. exit
  1952. ENDIF
  1953. minus_recv_start = minus_recv_start-1
  1954. recvw_m = recvw_m + 1
  1955. ENDDO
  1956. ENDIF
  1957. ! send to plus
  1958. sendw_p = 0
  1959. sendbeg_p = 1
  1960. IF ( me .LT. nt-1 ) THEN
  1961. ub = plus_send_start
  1962. sendbeg_p = pe - ub + 1
  1963. DO k = ub,pe-shw+1,-1
  1964. went = .TRUE.
  1965. IF ( is_intermediate ) THEN
  1966. kn = ( k - parent_start ) * parent_grid_ratio + 1 + 1 ;
  1967. CALL task_for_point (kn,1,nds,nde,1,1,nt,1,Px,Py,1,1,ierr) ! assume same alg. for x and y and just use x
  1968. ELSE
  1969. CALL task_for_point (k,1,ds,de,1,1,nt,1,Px,Py,1,1,ierr) ! assume same alg. for x and y and just use x
  1970. ENDIF
  1971. IF ( Px .NE. me-(iter-1) ) THEN
  1972. exit
  1973. ENDIF
  1974. plus_send_start = plus_send_start - 1
  1975. sendw_p = sendw_p + 1
  1976. ENDDO
  1977. ENDIF
  1978. ! recv from plus
  1979. recvw_p = 0
  1980. recvbeg_p = 1
  1981. IF ( me .LT. nt-1 ) THEN
  1982. lb = plus_recv_start
  1983. recvbeg_p = lb - pe
  1984. DO k = lb,pe+shw
  1985. went = .TRUE.
  1986. IF ( is_intermediate ) THEN
  1987. kn = ( k - parent_start ) * parent_grid_ratio + 1 + 1 ;
  1988. CALL task_for_point (kn,1,nds,nde,1,1,nt,1,Px,Py,1,1,ierr) ! assume same alg. for x and y and just use x
  1989. ELSE
  1990. CALL task_for_point (k,1,ds,de,1,1,nt,1,Px,Py,1,1,ierr) ! assume same alg. for x and y and just use x
  1991. ENDIF
  1992. IF ( Px .NE. me+iter ) THEN
  1993. exit
  1994. ENDIF
  1995. plus_recv_start = plus_recv_start + 1
  1996. recvw_p = recvw_p + 1
  1997. ENDDO
  1998. ENDIF
  1999. #else
  2000. if ( iter .eq. 1 ) then
  2001. went = .true.
  2002. else
  2003. went = .false.
  2004. endif
  2005. sendw_m = 0 ; sendw_p = 0 ; recvw_m = 0 ; recvw_p = 0
  2006. sendbeg_m = 1 ; if ( me .GT. 0 ) sendw_m = shw ;
  2007. sendbeg_p = 1 ; if ( me .LT. nt-1 ) sendw_p = shw
  2008. recvbeg_m = 1 ; if ( me .GT. 0 ) recvw_m = shw ;
  2009. recvbeg_p = 1 ; if ( me .LT. nt-1 ) recvw_p = shw ;
  2010. ! write(0,*)'shw ', shw , ' xy ',xy
  2011. ! write(0,*)' ds, de, ps, pe, nds,nde ',ds, de, ps, pe, nds,nde
  2012. ! write(0,*)'sendbeg_m, sendw_m, sendbeg_p, sendw_p, recvbeg_m, recvw_m, recvbeg_p, recvw_p '
  2013. ! write(0,*)sendbeg_m, sendw_m, sendbeg_p, sendw_p, recvbeg_m, recvw_m, recvbeg_p, recvw_p
  2014. #endif
  2015. !if ( went ) then
  2016. ! write(0,*)'shw ', shw , ' xy ',xy
  2017. ! write(0,*)' ds, de, ps, pe, nds,nde ',ds, de, ps, pe, nds,nde
  2018. ! write(0,*)'sendbeg_m, sendw_m, sendbeg_p, sendw_p, recvbeg_m, recvw_m, recvbeg_p, recvw_p '
  2019. ! write(0,*)sendbeg_m, sendw_m, sendbeg_p, sendw_p, recvbeg_m, recvw_m, recvbeg_p, recvw_p
  2020. !endif
  2021. rsl_comm_iter = went
  2022. END FUNCTION rsl_comm_iter
  2023. INTEGER FUNCTION wrf_dm_monitor_rank()
  2024. IMPLICIT NONE
  2025. wrf_dm_monitor_rank = 0
  2026. RETURN
  2027. END FUNCTION wrf_dm_monitor_rank
  2028. SUBROUTINE wrf_get_dm_communicator ( communicator )
  2029. USE module_dm , ONLY : local_communicator
  2030. IMPLICIT NONE
  2031. INTEGER , INTENT(OUT) :: communicator
  2032. communicator = local_communicator
  2033. RETURN
  2034. END SUBROUTINE wrf_get_dm_communicator
  2035. SUBROUTINE wrf_get_dm_communicator_x ( communicator )
  2036. USE module_dm , ONLY : local_communicator_x
  2037. IMPLICIT NONE
  2038. INTEGER , INTENT(OUT) :: communicator
  2039. communicator = local_communicator_x
  2040. RETURN
  2041. END SUBROUTINE wrf_get_dm_communicator_x
  2042. SUBROUTINE wrf_get_dm_communicator_y ( communicator )
  2043. USE module_dm , ONLY : local_communicator_y
  2044. IMPLICIT NONE
  2045. INTEGER , INTENT(OUT) :: communicator
  2046. communicator = local_communicator_y
  2047. RETURN
  2048. END SUBROUTINE wrf_get_dm_communicator_y
  2049. SUBROUTINE wrf_get_dm_iocommunicator ( iocommunicator )
  2050. USE module_dm , ONLY : local_iocommunicator
  2051. IMPLICIT NONE
  2052. INTEGER , INTENT(OUT) :: iocommunicator
  2053. iocommunicator = local_iocommunicator
  2054. RETURN
  2055. END SUBROUTINE wrf_get_dm_iocommunicator
  2056. SUBROUTINE wrf_set_dm_communicator ( communicator )
  2057. USE module_dm , ONLY : local_communicator
  2058. IMPLICIT NONE
  2059. INTEGER , INTENT(IN) :: communicator
  2060. local_communicator = communicator
  2061. RETURN
  2062. END SUBROUTINE wrf_set_dm_communicator
  2063. SUBROUTINE wrf_set_dm_iocommunicator ( iocommunicator )
  2064. USE module_dm , ONLY : local_iocommunicator
  2065. IMPLICIT NONE
  2066. INTEGER , INTENT(IN) :: iocommunicator
  2067. local_iocommunicator = iocommunicator
  2068. RETURN
  2069. END SUBROUTINE wrf_set_dm_iocommunicator
  2070. SUBROUTINE wrf_get_dm_ntasks_x ( retval )
  2071. USE module_dm , ONLY : ntasks_x
  2072. IMPLICIT NONE
  2073. INTEGER , INTENT(OUT) :: retval
  2074. retval = ntasks_x
  2075. RETURN
  2076. END SUBROUTINE wrf_get_dm_ntasks_x
  2077. SUBROUTINE wrf_get_dm_ntasks_y ( retval )
  2078. USE module_dm , ONLY : ntasks_y
  2079. IMPLICIT NONE
  2080. INTEGER , INTENT(OUT) :: retval
  2081. retval = ntasks_y
  2082. RETURN
  2083. END SUBROUTINE wrf_get_dm_ntasks_y
  2084. !!!!!!!!!!!!!!!!!!!!!!! PATCH TO GLOBAL !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  2085. SUBROUTINE wrf_patch_to_global_real (buf,globbuf,domdesc,stagger,ordering,&
  2086. DS1,DE1,DS2,DE2,DS3,DE3,&
  2087. MS1,ME1,MS2,ME2,MS3,ME3,&
  2088. PS1,PE1,PS2,PE2,PS3,PE3 )
  2089. IMPLICIT NONE
  2090. INTEGER DS1,DE1,DS2,DE2,DS3,DE3,&
  2091. MS1,ME1,MS2,ME2,MS3,ME3,&
  2092. PS1,PE1,PS2,PE2,PS3,PE3
  2093. CHARACTER *(*) stagger,ordering
  2094. INTEGER fid,domdesc
  2095. REAL globbuf(*)
  2096. REAL buf(*)
  2097. CALL wrf_patch_to_global_generic (buf,globbuf,domdesc,stagger,ordering,RWORDSIZE,&
  2098. DS1,DE1,DS2,DE2,DS3,DE3,&
  2099. MS1,ME1,MS2,ME2,MS3,ME3,&
  2100. PS1,PE1,PS2,PE2,PS3,PE3 )
  2101. RETURN
  2102. END SUBROUTINE wrf_patch_to_global_real
  2103. SUBROUTINE wrf_patch_to_global_double (buf,globbuf,domdesc,stagger,ordering,&
  2104. DS1,DE1,DS2,DE2,DS3,DE3,&
  2105. MS1,ME1,MS2,ME2,MS3,ME3,&
  2106. PS1,PE1,PS2,PE2,PS3,PE3 )
  2107. IMPLICIT NONE
  2108. INTEGER DS1,DE1,DS2,DE2,DS3,DE3,&
  2109. MS1,ME1,MS2,ME2,MS3,ME3,&
  2110. PS1,PE1,PS2,PE2,PS3,PE3
  2111. CHARACTER *(*) stagger,ordering
  2112. INTEGER fid,domdesc
  2113. ! this next declaration is REAL, not DOUBLE PRECISION because it will be autopromoted
  2114. ! to double precision by the compiler when WRF is compiled for 8 byte reals. Only reason
  2115. ! for having this separate routine is so we pass the correct MPI type to mpi_scatterv
  2116. ! since we were not indexing the globbuf and Field arrays it does not matter
  2117. REAL globbuf(*)
  2118. REAL buf(*)
  2119. CALL wrf_patch_to_global_generic (buf,globbuf,domdesc,stagger,ordering,DWORDSIZE,&
  2120. DS1,DE1,DS2,DE2,DS3,DE3,&
  2121. MS1,ME1,MS2,ME2,MS3,ME3,&
  2122. PS1,PE1,PS2,PE2,PS3,PE3 )
  2123. RETURN
  2124. END SUBROUTINE wrf_patch_to_global_double
  2125. SUBROUTINE wrf_patch_to_global_integer (buf,globbuf,domdesc,stagger,ordering,&
  2126. DS1,DE1,DS2,DE2,DS3,DE3,&
  2127. MS1,ME1,MS2,ME2,MS3,ME3,&
  2128. PS1,PE1,PS2,PE2,PS3,PE3 )
  2129. IMPLICIT NONE
  2130. INTEGER DS1,DE1,DS2,DE2,DS3,DE3,&
  2131. MS1,ME1,MS2,ME2,MS3,ME3,&
  2132. PS1,PE1,PS2,PE2,PS3,PE3
  2133. CHARACTER *(*) stagger,ordering
  2134. INTEGER fid,domdesc
  2135. INTEGER globbuf(*)
  2136. INTEGER buf(*)
  2137. CALL wrf_patch_to_global_generic (buf,globbuf,domdesc,stagger,ordering,IWORDSIZE,&
  2138. DS1,DE1,DS2,DE2,DS3,DE3,&
  2139. MS1,ME1,MS2,ME2,MS3,ME3,&
  2140. PS1,PE1,PS2,PE2,PS3,PE3 )
  2141. RETURN
  2142. END SUBROUTINE wrf_patch_to_global_integer
  2143. SUBROUTINE wrf_patch_to_global_logical (buf,globbuf,domdesc,stagger,ordering,&
  2144. DS1,DE1,DS2,DE2,DS3,DE3,&
  2145. MS1,ME1,MS2,ME2,MS3,ME3,&
  2146. PS1,PE1,PS2,PE2,PS3,PE3 )
  2147. IMPLICIT NONE
  2148. INTEGER DS1,DE1,DS2,DE2,DS3,DE3,&
  2149. MS1,ME1,MS2,ME2,MS3,ME3,&
  2150. PS1,PE1,PS2,PE2,PS3,PE3
  2151. CHARACTER *(*) stagger,ordering
  2152. INTEGER fid,domdesc
  2153. LOGICAL globbuf(*)
  2154. LOGICAL buf(*)
  2155. CALL wrf_patch_to_global_generic (buf,globbuf,domdesc,stagger,ordering,LWORDSIZE,&
  2156. DS1,DE1,DS2,DE2,DS3,DE3,&
  2157. MS1,ME1,MS2,ME2,MS3,ME3,&
  2158. PS1,PE1,PS2,PE2,PS3,PE3 )
  2159. RETURN
  2160. END SUBROUTINE wrf_patch_to_global_logical
  2161. #ifdef DEREF_KLUDGE
  2162. # define FRSTELEM (1)
  2163. #else
  2164. # define FRSTELEM
  2165. #endif
  2166. SUBROUTINE wrf_patch_to_global_generic (buf,globbuf,domdesc,stagger,ordering,typesize,&
  2167. DS1a,DE1a,DS2a,DE2a,DS3a,DE3a,&
  2168. MS1a,ME1a,MS2a,ME2a,MS3a,ME3a,&
  2169. PS1a,PE1a,PS2a,PE2a,PS3a,PE3a )
  2170. USE module_driver_constants
  2171. USE module_timing
  2172. USE module_wrf_error, ONLY : wrf_at_debug_level
  2173. USE module_dm, ONLY : local_communicator, ntasks
  2174. IMPLICIT NONE
  2175. INTEGER DS1a,DE1a,DS2a,DE2a,DS3a,DE3a,&
  2176. MS1a,ME1a,MS2a,ME2a,MS3a,ME3a,&
  2177. PS1a,PE1a,PS2a,PE2a,PS3a,PE3A
  2178. CHARACTER *(*) stagger,ordering
  2179. INTEGER domdesc,typesize,ierr
  2180. REAL globbuf(*)
  2181. REAL buf(*)
  2182. #ifndef STUBMPI
  2183. INTEGER DS1,DE1,DS2,DE2,DS3,DE3,&
  2184. MS1,ME1,MS2,ME2,MS3,ME3,&
  2185. PS1,PE1,PS2,PE2,PS3,PE3
  2186. INTEGER ids,ide,jds,jde,kds,kde,&
  2187. ims,ime,jms,jme,kms,kme,&
  2188. ips,ipe,jps,jpe,kps,kpe
  2189. LOGICAL, EXTERNAL :: wrf_dm_on_monitor, has_char
  2190. INTEGER i, j, k, ndim
  2191. INTEGER Patch(3,2), Gpatch(3,2,ntasks)
  2192. ! allocated further down, after the D indices are potentially recalculated for staggering
  2193. REAL, ALLOCATABLE :: tmpbuf( : )
  2194. REAL locbuf( (PE1a-PS1a+1)*(PE2a-PS2a+1)*(PE3a-PS3a+1)/RWORDSIZE*typesize+32 )
  2195. DS1 = DS1a ; DE1 = DE1a ; DS2=DS2a ; DE2 = DE2a ; DS3 = DS3a ; DE3 = DE3a
  2196. MS1 = MS1a ; ME1 = ME1a ; MS2=MS2a ; ME2 = ME2a ; MS3 = MS3a ; ME3 = ME3a
  2197. PS1 = PS1a ; PE1 = PE1a ; PS2=PS2a ; PE2 = PE2a ; PS3 = PS3a ; PE3 = PE3a
  2198. SELECT CASE ( TRIM(ordering) )
  2199. CASE ( 'xy', 'yx' )
  2200. ndim = 2
  2201. CASE DEFAULT
  2202. ndim = 3 ! where appropriate
  2203. END SELECT
  2204. SELECT CASE ( TRIM(ordering) )
  2205. CASE ( 'xyz','xy' )
  2206. ! the non-staggered variables come in at one-less than
  2207. ! domain dimensions, but code wants full domain spec, so
  2208. ! adjust if not staggered
  2209. IF ( .NOT. has_char( stagger, 'x' ) ) DE1 = DE1+1
  2210. IF ( .NOT. has_char( stagger, 'y' ) ) DE2 = DE2+1
  2211. IF ( ndim .EQ. 3 .AND. .NOT. has_char( stagger, 'z' ) ) DE3 = DE3+1
  2212. CASE ( 'yxz','yx' )
  2213. IF ( .NOT. has_char( stagger, 'x' ) ) DE2 = DE2+1
  2214. IF ( .NOT. has_char( stagger, 'y' ) ) DE1 = DE1+1
  2215. IF ( ndim .EQ. 3 .AND. .NOT. has_char( stagger, 'z' ) ) DE3 = DE3+1
  2216. CASE ( 'zxy' )
  2217. IF ( .NOT. has_char( stagger, 'x' ) ) DE2 = DE2+1
  2218. IF ( .NOT. has_char( stagger, 'y' ) ) DE3 = DE3+1
  2219. IF ( ndim .EQ. 3 .AND. .NOT. has_char( stagger, 'z' ) ) DE1 = DE1+1
  2220. CASE ( 'xzy' )
  2221. IF ( .NOT. has_char( stagger, 'x' ) ) DE1 = DE1+1
  2222. IF ( .NOT. has_char( stagger, 'y' ) ) DE3 = DE3+1
  2223. IF ( ndim .EQ. 3 .AND. .NOT. has_char( stagger, 'z' ) ) DE2 = DE2+1
  2224. CASE DEFAULT
  2225. END SELECT
  2226. ! moved to here to be after the potential recalculations of D dims
  2227. IF ( wrf_dm_on_monitor() ) THEN
  2228. ALLOCATE ( tmpbuf ( (DE1-DS1+1)*(DE2-DS2+1)*(DE3-DS3+1)/RWORDSIZE*typesize+32 ), STAT=ierr )
  2229. ELSE
  2230. ALLOCATE ( tmpbuf ( 1 ), STAT=ierr )
  2231. ENDIF
  2232. IF ( ierr .ne. 0 ) CALL wrf_error_fatal ('allocating tmpbuf in wrf_patch_to_global_generic')
  2233. Patch(1,1) = ps1 ; Patch(1,2) = pe1 ! use patch dims
  2234. Patch(2,1) = ps2 ; Patch(2,2) = pe2
  2235. Patch(3,1) = ps3 ; Patch(3,2) = pe3
  2236. IF ( typesize .EQ. RWORDSIZE ) THEN
  2237. CALL just_patch_r ( buf , locbuf , size(locbuf), &
  2238. PS1, PE1, PS2, PE2, PS3, PE3 , &
  2239. MS1, ME1, MS2, ME2, MS3, ME3 )
  2240. ELSE IF ( typesize .EQ. IWORDSIZE ) THEN
  2241. CALL just_patch_i ( buf , locbuf , size(locbuf), &
  2242. PS1, PE1, PS2, PE2, PS3, PE3 , &
  2243. MS1, ME1, MS2, ME2, MS3, ME3 )
  2244. ELSE IF ( typesize .EQ. DWORDSIZE ) THEN
  2245. CALL just_patch_d ( buf , locbuf , size(locbuf), &
  2246. PS1, PE1, PS2, PE2, PS3, PE3 , &
  2247. MS1, ME1, MS2, ME2, MS3, ME3 )
  2248. ELSE IF ( typesize .EQ. LWORDSIZE ) THEN
  2249. CALL just_patch_l ( buf , locbuf , size(locbuf), &
  2250. PS1, PE1, PS2, PE2, PS3, PE3 , &
  2251. MS1, ME1, MS2, ME2, MS3, ME3 )
  2252. ENDIF
  2253. ! defined in external/io_quilt
  2254. CALL collect_on_comm0 ( local_communicator , IWORDSIZE , &
  2255. Patch , 6 , &
  2256. GPatch , 6*ntasks )
  2257. CALL collect_on_comm0 ( local_communicator , typesize , &
  2258. locbuf , (pe1-ps1+1)*(pe2-ps2+1)*(pe3-ps3+1), &
  2259. tmpbuf FRSTELEM , (de1-ds1+1)*(de2-ds2+1)*(de3-ds3+1) )
  2260. ndim = len(TRIM(ordering))
  2261. IF ( wrf_at_debug_level(500) ) THEN
  2262. CALL start_timing
  2263. ENDIF
  2264. IF ( ndim .GE. 2 .AND. wrf_dm_on_monitor() ) THEN
  2265. IF ( typesize .EQ. RWORDSIZE ) THEN
  2266. CALL patch_2_outbuf_r ( tmpbuf FRSTELEM , globbuf , &
  2267. DS1, DE1, DS2, DE2, DS3, DE3 , &
  2268. GPATCH )
  2269. ELSE IF ( typesize .EQ. IWORDSIZE ) THEN
  2270. CALL patch_2_outbuf_i ( tmpbuf FRSTELEM , globbuf , &
  2271. DS1, DE1, DS2, DE2, DS3, DE3 , &
  2272. GPATCH )
  2273. ELSE IF ( typesize .EQ. DWORDSIZE ) THEN
  2274. CALL patch_2_outbuf_d ( tmpbuf FRSTELEM , globbuf , &
  2275. DS1, DE1, DS2, DE2, DS3, DE3 , &
  2276. GPATCH )
  2277. ELSE IF ( typesize .EQ. LWORDSIZE ) THEN
  2278. CALL patch_2_outbuf_l ( tmpbuf FRSTELEM , globbuf , &
  2279. DS1, DE1, DS2, DE2, DS3, DE3 , &
  2280. GPATCH )
  2281. ENDIF
  2282. ENDIF
  2283. IF ( wrf_at_debug_level(500) ) THEN
  2284. CALL end_timing('wrf_patch_to_global_generic')
  2285. ENDIF
  2286. DEALLOCATE( tmpbuf )
  2287. #endif
  2288. RETURN
  2289. END SUBROUTINE wrf_patch_to_global_generic
  2290. SUBROUTINE just_patch_i ( inbuf , outbuf, noutbuf, &
  2291. PS1,PE1,PS2,PE2,PS3,PE3, &
  2292. MS1,ME1,MS2,ME2,MS3,ME3 )
  2293. IMPLICIT NONE
  2294. INTEGER , INTENT(IN) :: noutbuf
  2295. INTEGER , DIMENSION(noutbuf) , INTENT(OUT) :: outbuf
  2296. INTEGER MS1,ME1,MS2,ME2,MS3,ME3
  2297. INTEGER PS1,PE1,PS2,PE2,PS3,PE3
  2298. INTEGER , DIMENSION( MS1:ME1,MS2:ME2,MS3:ME3 ) , INTENT(IN) :: inbuf
  2299. ! Local
  2300. INTEGER :: i,j,k,n , icurs
  2301. icurs = 1
  2302. DO k = PS3, PE3
  2303. DO j = PS2, PE2
  2304. DO i = PS1, PE1
  2305. outbuf( icurs ) = inbuf( i, j, k )
  2306. icurs = icurs + 1
  2307. ENDDO
  2308. ENDDO
  2309. ENDDO
  2310. RETURN
  2311. END SUBROUTINE just_patch_i
  2312. SUBROUTINE just_patch_r ( inbuf , outbuf, noutbuf, &
  2313. PS1,PE1,PS2,PE2,PS3,PE3, &
  2314. MS1,ME1,MS2,ME2,MS3,ME3 )
  2315. IMPLICIT NONE
  2316. INTEGER , INTENT(IN) :: noutbuf
  2317. REAL , DIMENSION(noutbuf) , INTENT(OUT) :: outbuf
  2318. INTEGER MS1,ME1,MS2,ME2,MS3,ME3
  2319. INTEGER PS1,PE1,PS2,PE2,PS3,PE3
  2320. REAL , DIMENSION( MS1:ME1,MS2:ME2,MS3:ME3 ) , INTENT(in) :: inbuf
  2321. ! Local
  2322. INTEGER :: i,j,k , icurs
  2323. icurs = 1
  2324. DO k = PS3, PE3
  2325. DO j = PS2, PE2
  2326. DO i = PS1, PE1
  2327. outbuf( icurs ) = inbuf( i, j, k )
  2328. icurs = icurs + 1
  2329. ENDDO
  2330. ENDDO
  2331. ENDDO
  2332. RETURN
  2333. END SUBROUTINE just_patch_r
  2334. SUBROUTINE just_patch_d ( inbuf , outbuf, noutbuf, &
  2335. PS1,PE1,PS2,PE2,PS3,PE3, &
  2336. MS1,ME1,MS2,ME2,MS3,ME3 )
  2337. IMPLICIT NONE
  2338. INTEGER , INTENT(IN) :: noutbuf
  2339. DOUBLE PRECISION , DIMENSION(noutbuf) , INTENT(OUT) :: outbuf
  2340. INTEGER MS1,ME1,MS2,ME2,MS3,ME3
  2341. INTEGER PS1,PE1,PS2,PE2,PS3,PE3
  2342. DOUBLE PRECISION , DIMENSION( MS1:ME1,MS2:ME2,MS3:ME3 ) , INTENT(in) :: inbuf
  2343. ! Local
  2344. INTEGER :: i,j,k,n , icurs
  2345. icurs = 1
  2346. DO k = PS3, PE3
  2347. DO j = PS2, PE2
  2348. DO i = PS1, PE1
  2349. outbuf( icurs ) = inbuf( i, j, k )
  2350. icurs = icurs + 1
  2351. ENDDO
  2352. ENDDO
  2353. ENDDO
  2354. RETURN
  2355. END SUBROUTINE just_patch_d
  2356. SUBROUTINE just_patch_l ( inbuf , outbuf, noutbuf, &
  2357. PS1,PE1,PS2,PE2,PS3,PE3, &
  2358. MS1,ME1,MS2,ME2,MS3,ME3 )
  2359. IMPLICIT NONE
  2360. INTEGER , INTENT(IN) :: noutbuf
  2361. LOGICAL , DIMENSION(noutbuf) , INTENT(OUT) :: outbuf
  2362. INTEGER MS1,ME1,MS2,ME2,MS3,ME3
  2363. INTEGER PS1,PE1,PS2,PE2,PS3,PE3
  2364. LOGICAL , DIMENSION( MS1:ME1,MS2:ME2,MS3:ME3 ) , INTENT(in) :: inbuf
  2365. ! Local
  2366. INTEGER :: i,j,k,n , icurs
  2367. icurs = 1
  2368. DO k = PS3, PE3
  2369. DO j = PS2, PE2
  2370. DO i = PS1, PE1
  2371. outbuf( icurs ) = inbuf( i, j, k )
  2372. icurs = icurs + 1
  2373. ENDDO
  2374. ENDDO
  2375. ENDDO
  2376. RETURN
  2377. END SUBROUTINE just_patch_l
  2378. SUBROUTINE patch_2_outbuf_r( inbuf, outbuf, &
  2379. DS1,DE1,DS2,DE2,DS3,DE3, &
  2380. GPATCH )
  2381. USE module_dm, ONLY : ntasks
  2382. IMPLICIT NONE
  2383. REAL , DIMENSION(*) , INTENT(IN) :: inbuf
  2384. INTEGER DS1,DE1,DS2,DE2,DS3,DE3,GPATCH(3,2,ntasks)
  2385. REAL , DIMENSION( DS1:DE1,DS2:DE2,DS3:DE3 ) , INTENT(out) :: outbuf
  2386. ! Local
  2387. INTEGER :: i,j,k,n , icurs
  2388. icurs = 1
  2389. DO n = 1, ntasks
  2390. DO k = GPATCH( 3,1,n ), GPATCH( 3,2,n )
  2391. DO j = GPATCH( 2,1,n ), GPATCH( 2,2,n )
  2392. DO i = GPATCH( 1,1,n ), GPATCH( 1,2,n )
  2393. outbuf( i, j, k ) = inbuf( icurs )
  2394. icurs = icurs + 1
  2395. ENDDO
  2396. ENDDO
  2397. ENDDO
  2398. ENDDO
  2399. RETURN
  2400. END SUBROUTINE patch_2_outbuf_r
  2401. SUBROUTINE patch_2_outbuf_i( inbuf, outbuf, &
  2402. DS1,DE1,DS2,DE2,DS3,DE3,&
  2403. GPATCH )
  2404. USE module_dm, ONLY : ntasks
  2405. IMPLICIT NONE
  2406. INTEGER , DIMENSION(*) , INTENT(IN) :: inbuf
  2407. INTEGER DS1,DE1,DS2,DE2,DS3,DE3,GPATCH(3,2,ntasks)
  2408. INTEGER , DIMENSION( DS1:DE1,DS2:DE2,DS3:DE3 ) , INTENT(out) :: outbuf
  2409. ! Local
  2410. INTEGER :: i,j,k,n , icurs
  2411. icurs = 1
  2412. DO n = 1, ntasks
  2413. DO k = GPATCH( 3,1,n ), GPATCH( 3,2,n )
  2414. DO j = GPATCH( 2,1,n ), GPATCH( 2,2,n )
  2415. DO i = GPATCH( 1,1,n ), GPATCH( 1,2,n )
  2416. outbuf( i, j, k ) = inbuf( icurs )
  2417. icurs = icurs + 1
  2418. ENDDO
  2419. ENDDO
  2420. ENDDO
  2421. ENDDO
  2422. RETURN
  2423. END SUBROUTINE patch_2_outbuf_i
  2424. SUBROUTINE patch_2_outbuf_d( inbuf, outbuf, &
  2425. DS1,DE1,DS2,DE2,DS3,DE3,&
  2426. GPATCH )
  2427. USE module_dm, ONLY : ntasks
  2428. IMPLICIT NONE
  2429. DOUBLE PRECISION , DIMENSION(*) , INTENT(IN) :: inbuf
  2430. INTEGER DS1,DE1,DS2,DE2,DS3,DE3,GPATCH(3,2,ntasks)
  2431. DOUBLE PRECISION , DIMENSION( DS1:DE1,DS2:DE2,DS3:DE3 ) , INTENT(out) :: outbuf
  2432. ! Local
  2433. INTEGER :: i,j,k,n , icurs
  2434. icurs = 1
  2435. DO n = 1, ntasks
  2436. DO k = GPATCH( 3,1,n ), GPATCH( 3,2,n )
  2437. DO j = GPATCH( 2,1,n ), GPATCH( 2,2,n )
  2438. DO i = GPATCH( 1,1,n ), GPATCH( 1,2,n )
  2439. outbuf( i, j, k ) = inbuf( icurs )
  2440. icurs = icurs + 1
  2441. ENDDO
  2442. ENDDO
  2443. ENDDO
  2444. ENDDO
  2445. RETURN
  2446. END SUBROUTINE patch_2_outbuf_d
  2447. SUBROUTINE patch_2_outbuf_l( inbuf, outbuf, &
  2448. DS1,DE1,DS2,DE2,DS3,DE3,&
  2449. GPATCH )
  2450. USE module_dm, ONLY : ntasks
  2451. IMPLICIT NONE
  2452. LOGICAL , DIMENSION(*) , INTENT(IN) :: inbuf
  2453. INTEGER DS1,DE1,DS2,DE2,DS3,DE3,GPATCH(3,2,ntasks)
  2454. LOGICAL , DIMENSION( DS1:DE1,DS2:DE2,DS3:DE3 ) , INTENT(out) :: outbuf
  2455. ! Local
  2456. INTEGER :: i,j,k,n , icurs
  2457. icurs = 1
  2458. DO n = 1, ntasks
  2459. DO k = GPATCH( 3,1,n ), GPATCH( 3,2,n )
  2460. DO j = GPATCH( 2,1,n ), GPATCH( 2,2,n )
  2461. DO i = GPATCH( 1,1,n ), GPATCH( 1,2,n )
  2462. outbuf( i, j, k ) = inbuf( icurs )
  2463. icurs = icurs + 1
  2464. ENDDO
  2465. ENDDO
  2466. ENDDO
  2467. ENDDO
  2468. RETURN
  2469. END SUBROUTINE patch_2_outbuf_l
  2470. !!!!!!!!!!!!!!!!!!!!!!! GLOBAL TO PATCH !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  2471. SUBROUTINE wrf_global_to_patch_real (globbuf,buf,domdesc,stagger,ordering,&
  2472. DS1,DE1,DS2,DE2,DS3,DE3,&
  2473. MS1,ME1,MS2,ME2,MS3,ME3,&
  2474. PS1,PE1,PS2,PE2,PS3,PE3 )
  2475. IMPLICIT NONE
  2476. INTEGER DS1,DE1,DS2,DE2,DS3,DE3,&
  2477. MS1,ME1,MS2,ME2,MS3,ME3,&
  2478. PS1,PE1,PS2,PE2,PS3,PE3
  2479. CHARACTER *(*) stagger,ordering
  2480. INTEGER fid,domdesc
  2481. REAL globbuf(*)
  2482. REAL buf(*)
  2483. CALL wrf_global_to_patch_generic (globbuf,buf,domdesc,stagger,ordering,RWORDSIZE,&
  2484. DS1,DE1,DS2,DE2,DS3,DE3,&
  2485. MS1,ME1,MS2,ME2,MS3,ME3,&
  2486. PS1,PE1,PS2,PE2,PS3,PE3 )
  2487. RETURN
  2488. END SUBROUTINE wrf_global_to_patch_real
  2489. SUBROUTINE wrf_global_to_patch_double (globbuf,buf,domdesc,stagger,ordering,&
  2490. DS1,DE1,DS2,DE2,DS3,DE3,&
  2491. MS1,ME1,MS2,ME2,MS3,ME3,&
  2492. PS1,PE1,PS2,PE2,PS3,PE3 )
  2493. IMPLICIT NONE
  2494. INTEGER DS1,DE1,DS2,DE2,DS3,DE3,&
  2495. MS1,ME1,MS2,ME2,MS3,ME3,&
  2496. PS1,PE1,PS2,PE2,PS3,PE3
  2497. CHARACTER *(*) stagger,ordering
  2498. INTEGER fid,domdesc
  2499. ! this next declaration is REAL, not DOUBLE PRECISION because it will be autopromoted
  2500. ! to double precision by the compiler when WRF is compiled for 8 byte reals. Only reason
  2501. ! for having this separate routine is so we pass the correct MPI type to mpi_scatterv
  2502. ! since we were not indexing the globbuf and Field arrays it does not matter
  2503. REAL globbuf(*)
  2504. REAL buf(*)
  2505. CALL wrf_global_to_patch_generic (globbuf,buf,domdesc,stagger,ordering,DWORDSIZE,&
  2506. DS1,DE1,DS2,DE2,DS3,DE3,&
  2507. MS1,ME1,MS2,ME2,MS3,ME3,&
  2508. PS1,PE1,PS2,PE2,PS3,PE3 )
  2509. RETURN
  2510. END SUBROUTINE wrf_global_to_patch_double
  2511. SUBROUTINE wrf_global_to_patch_integer (globbuf,buf,domdesc,stagger,ordering,&
  2512. DS1,DE1,DS2,DE2,DS3,DE3,&
  2513. MS1,ME1,MS2,ME2,MS3,ME3,&
  2514. PS1,PE1,PS2,PE2,PS3,PE3 )
  2515. IMPLICIT NONE
  2516. INTEGER DS1,DE1,DS2,DE2,DS3,DE3,&
  2517. MS1,ME1,MS2,ME2,MS3,ME3,&
  2518. PS1,PE1,PS2,PE2,PS3,PE3
  2519. CHARACTER *(*) stagger,ordering
  2520. INTEGER fid,domdesc
  2521. INTEGER globbuf(*)
  2522. INTEGER buf(*)
  2523. CALL wrf_global_to_patch_generic (globbuf,buf,domdesc,stagger,ordering,IWORDSIZE,&
  2524. DS1,DE1,DS2,DE2,DS3,DE3,&
  2525. MS1,ME1,MS2,ME2,MS3,ME3,&
  2526. PS1,PE1,PS2,PE2,PS3,PE3 )
  2527. RETURN
  2528. END SUBROUTINE wrf_global_to_patch_integer
  2529. SUBROUTINE wrf_global_to_patch_logical (globbuf,buf,domdesc,stagger,ordering,&
  2530. DS1,DE1,DS2,DE2,DS3,DE3,&
  2531. MS1,ME1,MS2,ME2,MS3,ME3,&
  2532. PS1,PE1,PS2,PE2,PS3,PE3 )
  2533. IMPLICIT NONE
  2534. INTEGER DS1,DE1,DS2,DE2,DS3,DE3,&
  2535. MS1,ME1,MS2,ME2,MS3,ME3,&
  2536. PS1,PE1,PS2,PE2,PS3,PE3
  2537. CHARACTER *(*) stagger,ordering
  2538. INTEGER fid,domdesc
  2539. LOGICAL globbuf(*)
  2540. LOGICAL buf(*)
  2541. CALL wrf_global_to_patch_generic (globbuf,buf,domdesc,stagger,ordering,LWORDSIZE,&
  2542. DS1,DE1,DS2,DE2,DS3,DE3,&
  2543. MS1,ME1,MS2,ME2,MS3,ME3,&
  2544. PS1,PE1,PS2,PE2,PS3,PE3 )
  2545. RETURN
  2546. END SUBROUTINE wrf_global_to_patch_logical
  2547. SUBROUTINE wrf_global_to_patch_generic (globbuf,buf,domdesc,stagger,ordering,typesize,&
  2548. DS1a,DE1a,DS2a,DE2a,DS3a,DE3a,&
  2549. MS1a,ME1a,MS2a,ME2a,MS3a,ME3a,&
  2550. PS1a,PE1a,PS2a,PE2a,PS3a,PE3a )
  2551. USE module_dm, ONLY : local_communicator, ntasks
  2552. USE module_driver_constants
  2553. IMPLICIT NONE
  2554. INTEGER DS1a,DE1a,DS2a,DE2a,DS3a,DE3a,&
  2555. MS1a,ME1a,MS2a,ME2a,MS3a,ME3a,&
  2556. PS1a,PE1a,PS2a,PE2a,PS3a,PE3A
  2557. CHARACTER *(*) stagger,ordering
  2558. INTEGER domdesc,typesize,ierr
  2559. REAL globbuf(*)
  2560. REAL buf(*)
  2561. #ifndef STUBMPI
  2562. INTEGER DS1,DE1,DS2,DE2,DS3,DE3,&
  2563. MS1,ME1,MS2,ME2,MS3,ME3,&
  2564. PS1,PE1,PS2,PE2,PS3,PE3
  2565. LOGICAL, EXTERNAL :: wrf_dm_on_monitor, has_char
  2566. INTEGER i,j,k,ord,ord2d,ndim
  2567. INTEGER Patch(3,2), Gpatch(3,2,ntasks)
  2568. REAL, ALLOCATABLE :: tmpbuf( : )
  2569. REAL locbuf( (PE1a-PS1a+1)*(PE2a-PS2a+1)*(PE3a-PS3a+1)/RWORDSIZE*typesize+32 )
  2570. DS1 = DS1a ; DE1 = DE1a ; DS2=DS2a ; DE2 = DE2a ; DS3 = DS3a ; DE3 = DE3a
  2571. MS1 = MS1a ; ME1 = ME1a ; MS2=MS2a ; ME2 = ME2a ; MS3 = MS3a ; ME3 = ME3a
  2572. PS1 = PS1a ; PE1 = PE1a ; PS2=PS2a ; PE2 = PE2a ; PS3 = PS3a ; PE3 = PE3a
  2573. SELECT CASE ( TRIM(ordering) )
  2574. CASE ( 'xy', 'yx' )
  2575. ndim = 2
  2576. CASE DEFAULT
  2577. ndim = 3 ! where appropriate
  2578. END SELECT
  2579. SELECT CASE ( TRIM(ordering) )
  2580. CASE ( 'xyz','xy' )
  2581. ! the non-staggered variables come in at one-less than
  2582. ! domain dimensions, but code wants full domain spec, so
  2583. ! adjust if not staggered
  2584. IF ( .NOT. has_char( stagger, 'x' ) ) DE1 = DE1+1
  2585. IF ( .NOT. has_char( stagger, 'y' ) ) DE2 = DE2+1
  2586. IF ( ndim .EQ. 3 .AND. .NOT. has_char( stagger, 'z' ) ) DE3 = DE3+1
  2587. CASE ( 'yxz','yx' )
  2588. IF ( .NOT. has_char( stagger, 'x' ) ) DE2 = DE2+1
  2589. IF ( .NOT. has_char( stagger, 'y' ) ) DE1 = DE1+1
  2590. IF ( ndim .EQ. 3 .AND. .NOT. has_char( stagger, 'z' ) ) DE3 = DE3+1
  2591. CASE ( 'zxy' )
  2592. IF ( .NOT. has_char( stagger, 'x' ) ) DE2 = DE2+1
  2593. IF ( .NOT. has_char( stagger, 'y' ) ) DE3 = DE3+1
  2594. IF ( ndim .EQ. 3 .AND. .NOT. has_char( stagger, 'z' ) ) DE1 = DE1+1
  2595. CASE ( 'xzy' )
  2596. IF ( .NOT. has_char( stagger, 'x' ) ) DE1 = DE1+1
  2597. IF ( .NOT. has_char( stagger, 'y' ) ) DE3 = DE3+1
  2598. IF ( ndim .EQ. 3 .AND. .NOT. has_char( stagger, 'z' ) ) DE2 = DE2+1
  2599. CASE DEFAULT
  2600. END SELECT
  2601. ! moved to here to be after the potential recalculations of D dims
  2602. IF ( wrf_dm_on_monitor() ) THEN
  2603. ALLOCATE ( tmpbuf ( (DE1-DS1+1)*(DE2-DS2+1)*(DE3-DS3+1)/RWORDSIZE*typesize+32 ), STAT=ierr )
  2604. ELSE
  2605. ALLOCATE ( tmpbuf ( 1 ), STAT=ierr )
  2606. ENDIF
  2607. IF ( ierr .ne. 0 ) CALL wrf_error_fatal ('allocating tmpbuf in wrf_global_to_patch_generic')
  2608. Patch(1,1) = ps1 ; Patch(1,2) = pe1 ! use patch dims
  2609. Patch(2,1) = ps2 ; Patch(2,2) = pe2
  2610. Patch(3,1) = ps3 ; Patch(3,2) = pe3
  2611. ! defined in external/io_quilt
  2612. CALL collect_on_comm0 ( local_communicator , IWORDSIZE , &
  2613. Patch , 6 , &
  2614. GPatch , 6*ntasks )
  2615. ndim = len(TRIM(ordering))
  2616. IF ( wrf_dm_on_monitor() .AND. ndim .GE. 2 ) THEN
  2617. IF ( typesize .EQ. RWORDSIZE ) THEN
  2618. CALL outbuf_2_patch_r ( globbuf , tmpbuf FRSTELEM , &
  2619. DS1, DE1, DS2, DE2, DS3, DE3 , &
  2620. MS1, ME1, MS2, ME2, MS3, ME3 , &
  2621. GPATCH )
  2622. ELSE IF ( typesize .EQ. IWORDSIZE ) THEN
  2623. CALL outbuf_2_patch_i ( globbuf , tmpbuf FRSTELEM , &
  2624. DS1, DE1, DS2, DE2, DS3, DE3 , &
  2625. GPATCH )
  2626. ELSE IF ( typesize .EQ. DWORDSIZE ) THEN
  2627. CALL outbuf_2_patch_d ( globbuf , tmpbuf FRSTELEM , &
  2628. DS1, DE1, DS2, DE2, DS3, DE3 , &
  2629. GPATCH )
  2630. ELSE IF ( typesize .EQ. LWORDSIZE ) THEN
  2631. CALL outbuf_2_patch_l ( globbuf , tmpbuf FRSTELEM , &
  2632. DS1, DE1, DS2, DE2, DS3, DE3 , &
  2633. GPATCH )
  2634. ENDIF
  2635. ENDIF
  2636. CALL dist_on_comm0 ( local_communicator , typesize , &
  2637. tmpbuf FRSTELEM , (de1-ds1+1)*(de2-ds2+1)*(de3-ds3+1) , &
  2638. locbuf , (pe1-ps1+1)*(pe2-ps2+1)*(pe3-ps3+1) )
  2639. IF ( typesize .EQ. RWORDSIZE ) THEN
  2640. CALL all_sub_r ( locbuf , buf , &
  2641. PS1, PE1, PS2, PE2, PS3, PE3 , &
  2642. MS1, ME1, MS2, ME2, MS3, ME3 )
  2643. ELSE IF ( typesize .EQ. IWORDSIZE ) THEN
  2644. CALL all_sub_i ( locbuf , buf , &
  2645. PS1, PE1, PS2, PE2, PS3, PE3 , &
  2646. MS1, ME1, MS2, ME2, MS3, ME3 )
  2647. ELSE IF ( typesize .EQ. DWORDSIZE ) THEN
  2648. CALL all_sub_d ( locbuf , buf , &
  2649. PS1, PE1, PS2, PE2, PS3, PE3 , &
  2650. MS1, ME1, MS2, ME2, MS3, ME3 )
  2651. ELSE IF ( typesize .EQ. LWORDSIZE ) THEN
  2652. CALL all_sub_l ( locbuf , buf , &
  2653. PS1, PE1, PS2, PE2, PS3, PE3 , &
  2654. MS1, ME1, MS2, ME2, MS3, ME3 )
  2655. ENDIF
  2656. DEALLOCATE ( tmpbuf )
  2657. #endif
  2658. RETURN
  2659. END SUBROUTINE wrf_global_to_patch_generic
  2660. SUBROUTINE all_sub_i ( inbuf , outbuf, &
  2661. PS1,PE1,PS2,PE2,PS3,PE3, &
  2662. MS1,ME1,MS2,ME2,MS3,ME3 )
  2663. IMPLICIT NONE
  2664. INTEGER , DIMENSION(*) , INTENT(IN) :: inbuf
  2665. INTEGER MS1,ME1,MS2,ME2,MS3,ME3
  2666. INTEGER PS1,PE1,PS2,PE2,PS3,PE3
  2667. INTEGER , DIMENSION( MS1:ME1,MS2:ME2,MS3:ME3 ) , INTENT(OUT) :: outbuf
  2668. ! Local
  2669. INTEGER :: i,j,k,n , icurs
  2670. icurs = 1
  2671. DO k = PS3, PE3
  2672. DO j = PS2, PE2
  2673. DO i = PS1, PE1
  2674. outbuf( i, j, k ) = inbuf ( icurs )
  2675. icurs = icurs + 1
  2676. ENDDO
  2677. ENDDO
  2678. ENDDO
  2679. RETURN
  2680. END SUBROUTINE all_sub_i
  2681. SUBROUTINE all_sub_r ( inbuf , outbuf, &
  2682. PS1,PE1,PS2,PE2,PS3,PE3, &
  2683. MS1,ME1,MS2,ME2,MS3,ME3 )
  2684. IMPLICIT NONE
  2685. REAL , DIMENSION(*) , INTENT(IN) :: inbuf
  2686. INTEGER MS1,ME1,MS2,ME2,MS3,ME3
  2687. INTEGER PS1,PE1,PS2,PE2,PS3,PE3
  2688. REAL , DIMENSION( MS1:ME1,MS2:ME2,MS3:ME3 ) , INTENT(OUT) :: outbuf
  2689. ! Local
  2690. INTEGER :: i,j,k,n , icurs
  2691. icurs = 1
  2692. DO k = PS3, PE3
  2693. DO j = PS2, PE2
  2694. DO i = PS1, PE1
  2695. outbuf( i, j, k ) = inbuf ( icurs )
  2696. icurs = icurs + 1
  2697. ENDDO
  2698. ENDDO
  2699. ENDDO
  2700. RETURN
  2701. END SUBROUTINE all_sub_r
  2702. SUBROUTINE all_sub_d ( inbuf , outbuf, &
  2703. PS1,PE1,PS2,PE2,PS3,PE3, &
  2704. MS1,ME1,MS2,ME2,MS3,ME3 )
  2705. IMPLICIT NONE
  2706. DOUBLE PRECISION , DIMENSION(*) , INTENT(IN) :: inbuf
  2707. INTEGER MS1,ME1,MS2,ME2,MS3,ME3
  2708. INTEGER PS1,PE1,PS2,PE2,PS3,PE3
  2709. DOUBLE PRECISION , DIMENSION( MS1:ME1,MS2:ME2,MS3:ME3 ) , INTENT(OUT) :: outbuf
  2710. ! Local
  2711. INTEGER :: i,j,k,n , icurs
  2712. icurs = 1
  2713. DO k = PS3, PE3
  2714. DO j = PS2, PE2
  2715. DO i = PS1, PE1
  2716. outbuf( i, j, k ) = inbuf ( icurs )
  2717. icurs = icurs + 1
  2718. ENDDO
  2719. ENDDO
  2720. ENDDO
  2721. RETURN
  2722. END SUBROUTINE all_sub_d
  2723. SUBROUTINE all_sub_l ( inbuf , outbuf, &
  2724. PS1,PE1,PS2,PE2,PS3,PE3, &
  2725. MS1,ME1,MS2,ME2,MS3,ME3 )
  2726. IMPLICIT NONE
  2727. LOGICAL , DIMENSION(*) , INTENT(IN) :: inbuf
  2728. INTEGER MS1,ME1,MS2,ME2,MS3,ME3
  2729. INTEGER PS1,PE1,PS2,PE2,PS3,PE3
  2730. LOGICAL , DIMENSION( MS1:ME1,MS2:ME2,MS3:ME3 ) , INTENT(OUT) :: outbuf
  2731. ! Local
  2732. INTEGER :: i,j,k,n , icurs
  2733. icurs = 1
  2734. DO k = PS3, PE3
  2735. DO j = PS2, PE2
  2736. DO i = PS1, PE1
  2737. outbuf( i, j, k ) = inbuf ( icurs )
  2738. icurs = icurs + 1
  2739. ENDDO
  2740. ENDDO
  2741. ENDDO
  2742. RETURN
  2743. END SUBROUTINE all_sub_l
  2744. SUBROUTINE outbuf_2_patch_r( inbuf, outbuf, &
  2745. DS1,DE1,DS2,DE2,DS3,DE3, &
  2746. MS1, ME1, MS2, ME2, MS3, ME3 , &
  2747. GPATCH )
  2748. USE module_dm, ONLY : ntasks
  2749. IMPLICIT NONE
  2750. REAL , DIMENSION(*) , INTENT(OUT) :: outbuf
  2751. INTEGER DS1,DE1,DS2,DE2,DS3,DE3,GPATCH(3,2,ntasks)
  2752. INTEGER MS1,ME1,MS2,ME2,MS3,ME3
  2753. REAL , DIMENSION( DS1:DE1,DS2:DE2,DS3:DE3 ) , INTENT(IN) :: inbuf
  2754. ! Local
  2755. INTEGER :: i,j,k,n , icurs
  2756. icurs = 1
  2757. DO n = 1, ntasks
  2758. DO k = GPATCH( 3,1,n ), GPATCH( 3,2,n )
  2759. DO j = GPATCH( 2,1,n ), GPATCH( 2,2,n )
  2760. DO i = GPATCH( 1,1,n ), GPATCH( 1,2,n )
  2761. outbuf( icurs ) = inbuf( i,j,k )
  2762. icurs = icurs + 1
  2763. ENDDO
  2764. ENDDO
  2765. ENDDO
  2766. ENDDO
  2767. RETURN
  2768. END SUBROUTINE outbuf_2_patch_r
  2769. SUBROUTINE outbuf_2_patch_i( inbuf, outbuf, &
  2770. DS1,DE1,DS2,DE2,DS3,DE3,&
  2771. GPATCH )
  2772. USE module_dm, ONLY : ntasks
  2773. IMPLICIT NONE
  2774. INTEGER , DIMENSION(*) , INTENT(OUT) :: outbuf
  2775. INTEGER DS1,DE1,DS2,DE2,DS3,DE3,GPATCH(3,2,ntasks)
  2776. INTEGER , DIMENSION( DS1:DE1,DS2:DE2,DS3:DE3 ) , INTENT(IN) :: inbuf
  2777. ! Local
  2778. INTEGER :: i,j,k,n , icurs
  2779. icurs = 1
  2780. DO n = 1, ntasks
  2781. DO k = GPATCH( 3,1,n ), GPATCH( 3,2,n )
  2782. DO j = GPATCH( 2,1,n ), GPATCH( 2,2,n )
  2783. DO i = GPATCH( 1,1,n ), GPATCH( 1,2,n )
  2784. outbuf( icurs ) = inbuf( i,j,k )
  2785. icurs = icurs + 1
  2786. ENDDO
  2787. ENDDO
  2788. ENDDO
  2789. ENDDO
  2790. RETURN
  2791. END SUBROUTINE outbuf_2_patch_i
  2792. SUBROUTINE outbuf_2_patch_d( inbuf, outbuf, &
  2793. DS1,DE1,DS2,DE2,DS3,DE3,&
  2794. GPATCH )
  2795. USE module_dm, ONLY : ntasks
  2796. IMPLICIT NONE
  2797. DOUBLE PRECISION , DIMENSION(*) , INTENT(OUT) :: outbuf
  2798. INTEGER DS1,DE1,DS2,DE2,DS3,DE3,GPATCH(3,2,ntasks)
  2799. DOUBLE PRECISION , DIMENSION( DS1:DE1,DS2:DE2,DS3:DE3 ) , INTENT(IN) :: inbuf
  2800. ! Local
  2801. INTEGER :: i,j,k,n , icurs
  2802. icurs = 1
  2803. DO n = 1, ntasks
  2804. DO k = GPATCH( 3,1,n ), GPATCH( 3,2,n )
  2805. DO j = GPATCH( 2,1,n ), GPATCH( 2,2,n )
  2806. DO i = GPATCH( 1,1,n ), GPATCH( 1,2,n )
  2807. outbuf( icurs ) = inbuf( i,j,k )
  2808. icurs = icurs + 1
  2809. ENDDO
  2810. ENDDO
  2811. ENDDO
  2812. ENDDO
  2813. RETURN
  2814. END SUBROUTINE outbuf_2_patch_d
  2815. SUBROUTINE outbuf_2_patch_l( inbuf, outbuf, &
  2816. DS1,DE1,DS2,DE2,DS3,DE3,&
  2817. GPATCH )
  2818. USE module_dm, ONLY : ntasks
  2819. IMPLICIT NONE
  2820. LOGICAL , DIMENSION(*) , INTENT(OUT) :: outbuf
  2821. INTEGER DS1,DE1,DS2,DE2,DS3,DE3,GPATCH(3,2,ntasks)
  2822. LOGICAL , DIMENSION( DS1:DE1,DS2:DE2,DS3:DE3 ) , INTENT(IN) :: inbuf
  2823. ! Local
  2824. INTEGER :: i,j,k,n , icurs
  2825. icurs = 1
  2826. DO n = 1, ntasks
  2827. DO k = GPATCH( 3,1,n ), GPATCH( 3,2,n )
  2828. DO j = GPATCH( 2,1,n ), GPATCH( 2,2,n )
  2829. DO i = GPATCH( 1,1,n ), GPATCH( 1,2,n )
  2830. outbuf( icurs ) = inbuf( i,j,k )
  2831. icurs = icurs + 1
  2832. ENDDO
  2833. ENDDO
  2834. ENDDO
  2835. ENDDO
  2836. RETURN
  2837. END SUBROUTINE outbuf_2_patch_l
  2838. !------------------------------------------------------------------
  2839. #if ( EM_CORE == 1 && DA_CORE != 1 )
  2840. !------------------------------------------------------------------
  2841. SUBROUTINE force_domain_em_part2 ( grid, ngrid, config_flags &
  2842. !
  2843. #include "dummy_new_args.inc"
  2844. !
  2845. )
  2846. USE module_state_description
  2847. USE module_domain, ONLY : domain, get_ijk_from_grid
  2848. USE module_configure, ONLY : grid_config_rec_type
  2849. USE module_dm, ONLY : ntasks, ntasks_x, ntasks_y, local_communicator, mytask
  2850. USE module_comm_nesting_dm, ONLY : halo_force_down_sub
  2851. IMPLICIT NONE
  2852. !
  2853. TYPE(domain), POINTER :: grid ! name of the grid being dereferenced (must be "grid")
  2854. TYPE(domain), POINTER :: ngrid
  2855. #include <dummy_new_decl.inc>
  2856. INTEGER nlev, msize
  2857. INTEGER i,j,pig,pjg,cm,cn,nig,njg,retval,k
  2858. TYPE (grid_config_rec_type) :: config_flags
  2859. REAL xv(500)
  2860. INTEGER :: cids, cide, cjds, cjde, ckds, ckde, &
  2861. cims, cime, cjms, cjme, ckms, ckme, &
  2862. cips, cipe, cjps, cjpe, ckps, ckpe
  2863. INTEGER :: nids, nide, njds, njde, nkds, nkde, &
  2864. nims, nime, njms, njme, nkms, nkme, &
  2865. nips, nipe, njps, njpe, nkps, nkpe
  2866. INTEGER :: ids, ide, jds, jde, kds, kde, &
  2867. ims, ime, jms, jme, kms, kme, &
  2868. ips, ipe, jps, jpe, kps, kpe
  2869. INTEGER idim1,idim2,idim3,idim4,idim5,idim6,idim7,itrace
  2870. REAL dummy_xs, dummy_xe, dummy_ys, dummy_ye
  2871. CALL get_ijk_from_grid ( grid , &
  2872. cids, cide, cjds, cjde, ckds, ckde, &
  2873. cims, cime, cjms, cjme, ckms, ckme, &
  2874. cips, cipe, cjps, cjpe, ckps, ckpe )
  2875. CALL get_ijk_from_grid ( ngrid , &
  2876. nids, nide, njds, njde, nkds, nkde, &
  2877. nims, nime, njms, njme, nkms, nkme, &
  2878. nips, nipe, njps, njpe, nkps, nkpe )
  2879. nlev = ckde - ckds + 1
  2880. #include "nest_interpdown_unpack.inc"
  2881. CALL get_ijk_from_grid ( grid , &
  2882. ids, ide, jds, jde, kds, kde, &
  2883. ims, ime, jms, jme, kms, kme, &
  2884. ips, ipe, jps, jpe, kps, kpe )
  2885. #include "HALO_FORCE_DOWN.inc"
  2886. ! code here to interpolate the data into the nested domain
  2887. # include "nest_forcedown_interp.inc"
  2888. RETURN
  2889. END SUBROUTINE force_domain_em_part2
  2890. !------------------------------------------------------------------
  2891. SUBROUTINE interp_domain_em_part1 ( grid, intermediate_grid, ngrid, config_flags &
  2892. !
  2893. #include "dummy_new_args.inc"
  2894. !
  2895. )
  2896. USE module_state_description
  2897. USE module_domain, ONLY : domain, get_ijk_from_grid
  2898. USE module_configure, ONLY : grid_config_rec_type
  2899. USE module_dm, ONLY : ntasks, ntasks_x, ntasks_y, itrace, local_communicator, &
  2900. mytask, get_dm_max_halo_width
  2901. USE module_timing
  2902. IMPLICIT NONE
  2903. !
  2904. TYPE(domain), POINTER :: grid ! name of the grid being dereferenced (must be "grid")
  2905. TYPE(domain), POINTER :: intermediate_grid
  2906. TYPE(domain), POINTER :: ngrid
  2907. #include <dummy_new_decl.inc>
  2908. INTEGER nlev, msize
  2909. INTEGER i,j,pig,pjg,cm,cn,nig,njg,retval,k
  2910. INTEGER iparstrt,jparstrt,sw
  2911. TYPE (grid_config_rec_type) :: config_flags
  2912. REAL xv(500)
  2913. INTEGER :: cids, cide, cjds, cjde, ckds, ckde, &
  2914. cims, cime, cjms, cjme, ckms, ckme, &
  2915. cips, cipe, cjps, cjpe, ckps, ckpe
  2916. INTEGER :: iids, iide, ijds, ijde, ikds, ikde, &
  2917. iims, iime, ijms, ijme, ikms, ikme, &
  2918. iips, iipe, ijps, ijpe, ikps, ikpe
  2919. INTEGER :: nids, nide, njds, njde, nkds, nkde, &
  2920. nims, nime, njms, njme, nkms, nkme, &
  2921. nips, nipe, njps, njpe, nkps, nkpe
  2922. INTEGER idim1,idim2,idim3,idim4,idim5,idim6,idim7
  2923. INTEGER icoord, jcoord, idim_cd, jdim_cd, pgr
  2924. INTEGER thisdomain_max_halo_width
  2925. INTEGER local_comm, myproc, nproc
  2926. CALL wrf_get_dm_communicator ( local_comm )
  2927. CALL wrf_get_myproc( myproc )
  2928. CALL wrf_get_nproc( nproc )
  2929. CALL get_ijk_from_grid ( grid , &
  2930. cids, cide, cjds, cjde, ckds, ckde, &
  2931. cims, cime, cjms, cjme, ckms, ckme, &
  2932. cips, cipe, cjps, cjpe, ckps, ckpe )
  2933. CALL get_ijk_from_grid ( intermediate_grid , &
  2934. iids, iide, ijds, ijde, ikds, ikde, &
  2935. iims, iime, ijms, ijme, ikms, ikme, &
  2936. iips, iipe, ijps, ijpe, ikps, ikpe )
  2937. CALL get_ijk_from_grid ( ngrid , &
  2938. nids, nide, njds, njde, nkds, nkde, &
  2939. nims, nime, njms, njme, nkms, nkme, &
  2940. nips, nipe, njps, njpe, nkps, nkpe )
  2941. CALL nl_get_parent_grid_ratio ( ngrid%id, pgr )
  2942. CALL nl_get_i_parent_start ( intermediate_grid%id, iparstrt )
  2943. CALL nl_get_j_parent_start ( intermediate_grid%id, jparstrt )
  2944. CALL nl_get_shw ( intermediate_grid%id, sw )
  2945. icoord = iparstrt - sw
  2946. jcoord = jparstrt - sw
  2947. idim_cd = iide - iids + 1
  2948. jdim_cd = ijde - ijds + 1
  2949. nlev = ckde - ckds + 1
  2950. ! get max_halo_width for parent. It may be smaller if it is moad
  2951. CALL get_dm_max_halo_width ( grid%id , thisdomain_max_halo_width )
  2952. #include "nest_interpdown_pack.inc"
  2953. CALL rsl_lite_bcast_msgs( myproc, nproc, local_comm )
  2954. RETURN
  2955. END SUBROUTINE interp_domain_em_part1
  2956. !------------------------------------------------------------------
  2957. SUBROUTINE interp_domain_em_part2 ( grid, ngrid, config_flags &
  2958. !
  2959. #include "dummy_new_args.inc"
  2960. !
  2961. )
  2962. USE module_state_description
  2963. USE module_domain, ONLY : domain, get_ijk_from_grid
  2964. USE module_configure, ONLY : grid_config_rec_type
  2965. USE module_dm, ONLY : ntasks, ntasks_x, ntasks_y, itrace, local_communicator, &
  2966. mytask, get_dm_max_halo_width
  2967. USE module_comm_nesting_dm, ONLY : halo_interp_down_sub
  2968. IMPLICIT NONE
  2969. !
  2970. TYPE(domain), POINTER :: grid ! name of the grid being dereferenced (must be "grid")
  2971. TYPE(domain), POINTER :: ngrid
  2972. #include <dummy_new_decl.inc>
  2973. INTEGER nlev, msize
  2974. INTEGER i,j,pig,pjg,cm,cn,nig,njg,retval,k
  2975. TYPE (grid_config_rec_type) :: config_flags
  2976. REAL xv(500)
  2977. INTEGER :: cids, cide, cjds, cjde, ckds, ckde, &
  2978. cims, cime, cjms, cjme, ckms, ckme, &
  2979. cips, cipe, cjps, cjpe, ckps, ckpe
  2980. INTEGER :: nids, nide, njds, njde, nkds, nkde, &
  2981. nims, nime, njms, njme, nkms, nkme, &
  2982. nips, nipe, njps, njpe, nkps, nkpe
  2983. INTEGER :: ids, ide, jds, jde, kds, kde, &
  2984. ims, ime, jms, jme, kms, kme, &
  2985. ips, ipe, jps, jpe, kps, kpe
  2986. INTEGER idim1,idim2,idim3,idim4,idim5,idim6,idim7
  2987. INTEGER myproc
  2988. INTEGER ierr
  2989. INTEGER thisdomain_max_halo_width
  2990. CALL get_ijk_from_grid ( grid , &
  2991. cids, cide, cjds, cjde, ckds, ckde, &
  2992. cims, cime, cjms, cjme, ckms, ckme, &
  2993. cips, cipe, cjps, cjpe, ckps, ckpe )
  2994. CALL get_ijk_from_grid ( ngrid , &
  2995. nids, nide, njds, njde, nkds, nkde, &
  2996. nims, nime, njms, njme, nkms, nkme, &
  2997. nips, nipe, njps, njpe, nkps, nkpe )
  2998. nlev = ckde - ckds + 1
  2999. CALL get_dm_max_halo_width ( ngrid%id , thisdomain_max_halo_width )
  3000. #include "nest_interpdown_unpack.inc"
  3001. CALL get_ijk_from_grid ( grid , &
  3002. ids, ide, jds, jde, kds, kde, &
  3003. ims, ime, jms, jme, kms, kme, &
  3004. ips, ipe, jps, jpe, kps, kpe )
  3005. #include "HALO_INTERP_DOWN.inc"
  3006. # include "nest_interpdown_interp.inc"
  3007. RETURN
  3008. END SUBROUTINE interp_domain_em_part2
  3009. !------------------------------------------------------------------
  3010. SUBROUTINE feedback_nest_prep ( grid, config_flags &
  3011. !
  3012. #include "dummy_new_args.inc"
  3013. !
  3014. )
  3015. USE module_state_description
  3016. USE module_domain, ONLY : domain, get_ijk_from_grid
  3017. USE module_configure, ONLY : grid_config_rec_type
  3018. USE module_dm, ONLY : ntasks, ntasks_x, ntasks_y, itrace, local_communicator, mytask
  3019. USE module_comm_nesting_dm, ONLY : halo_interp_up_sub
  3020. IMPLICIT NONE
  3021. !
  3022. TYPE(domain), TARGET :: grid ! name of the grid being dereferenced (must be "grid")
  3023. TYPE (grid_config_rec_type) :: config_flags ! configureation flags, has vertical dim of
  3024. ! soil temp, moisture, etc., has vertical dim
  3025. ! of soil categories
  3026. #include <dummy_new_decl.inc>
  3027. INTEGER :: ids, ide, jds, jde, kds, kde, &
  3028. ims, ime, jms, jme, kms, kme, &
  3029. ips, ipe, jps, jpe, kps, kpe
  3030. INTEGER idim1,idim2,idim3,idim4,idim5,idim6,idim7
  3031. INTEGER :: idum1, idum2
  3032. CALL get_ijk_from_grid ( grid , &
  3033. ids, ide, jds, jde, kds, kde, &
  3034. ims, ime, jms, jme, kms, kme, &
  3035. ips, ipe, jps, jpe, kps, kpe )
  3036. #ifdef DM_PARALLEL
  3037. #include "HALO_INTERP_UP.inc"
  3038. #endif
  3039. END SUBROUTINE feedback_nest_prep
  3040. !------------------------------------------------------------------
  3041. SUBROUTINE feedback_domain_em_part1 ( grid, ngrid, config_flags &
  3042. !
  3043. #include "dummy_new_args.inc"
  3044. !
  3045. )
  3046. USE module_state_description
  3047. USE module_domain, ONLY : domain, get_ijk_from_grid
  3048. USE module_configure, ONLY : grid_config_rec_type, model_config_rec, model_to_grid_config_rec
  3049. USE module_dm, ONLY : ntasks, ntasks_x, ntasks_y, itrace, local_communicator, mytask, &
  3050. ipe_save, jpe_save, ips_save, jps_save
  3051. IMPLICIT NONE
  3052. !
  3053. TYPE(domain), POINTER :: grid ! name of the grid being dereferenced (must be "grid")
  3054. TYPE(domain), POINTER :: ngrid
  3055. #include <dummy_new_decl.inc>
  3056. INTEGER nlev, msize
  3057. INTEGER i,j,pig,pjg,cm,cn,nig,njg,retval,k
  3058. TYPE(domain), POINTER :: xgrid
  3059. TYPE (grid_config_rec_type) :: config_flags, nconfig_flags
  3060. REAL xv(500)
  3061. INTEGER :: cids, cide, cjds, cjde, ckds, ckde, &
  3062. cims, cime, cjms, cjme, ckms, ckme, &
  3063. cips, cipe, cjps, cjpe, ckps, ckpe
  3064. INTEGER :: nids, nide, njds, njde, nkds, nkde, &
  3065. nims, nime, njms, njme, nkms, nkme, &
  3066. nips, nipe, njps, njpe, nkps, nkpe
  3067. INTEGER idim1,idim2,idim3,idim4,idim5,idim6,idim7
  3068. INTEGER local_comm, myproc, nproc, idum1, idum2
  3069. INTEGER thisdomain_max_halo_width
  3070. INTERFACE
  3071. SUBROUTINE feedback_nest_prep ( grid, config_flags &
  3072. !
  3073. #include "dummy_new_args.inc"
  3074. !
  3075. )
  3076. USE module_state_description
  3077. USE module_domain, ONLY : domain
  3078. USE module_configure, ONLY : grid_config_rec_type
  3079. !
  3080. TYPE (grid_config_rec_type) :: config_flags
  3081. TYPE(domain), TARGET :: grid
  3082. #include <dummy_new_decl.inc>
  3083. END SUBROUTINE feedback_nest_prep
  3084. END INTERFACE
  3085. !
  3086. CALL wrf_get_dm_communicator ( local_comm )
  3087. CALL wrf_get_myproc( myproc )
  3088. CALL wrf_get_nproc( nproc )
  3089. !
  3090. ! intermediate grid
  3091. CALL get_ijk_from_grid ( grid , &
  3092. cids, cide, cjds, cjde, ckds, ckde, &
  3093. cims, cime, cjms, cjme, ckms, ckme, &
  3094. cips, cipe, cjps, cjpe, ckps, ckpe )
  3095. ! nest grid
  3096. CALL get_ijk_from_grid ( ngrid , &
  3097. nids, nide, njds, njde, nkds, nkde, &
  3098. nims, nime, njms, njme, nkms, nkme, &
  3099. nips, nipe, njps, njpe, nkps, nkpe )
  3100. nlev = ckde - ckds + 1
  3101. ips_save = ngrid%i_parent_start ! used in feedback_domain_em_part2 below
  3102. jps_save = ngrid%j_parent_start
  3103. ipe_save = ngrid%i_parent_start + (nide-nids+1) / ngrid%parent_grid_ratio - 1
  3104. jpe_save = ngrid%j_parent_start + (njde-njds+1) / ngrid%parent_grid_ratio - 1
  3105. ! feedback_nest_prep invokes a halo exchange on the ngrid. It is done this way
  3106. ! in a separate routine because the HALOs need the data to be dereference from the
  3107. ! grid data structure and, in this routine, the dereferenced fields are related to
  3108. ! the intermediate domain, not the nest itself. Save the current grid pointer to intermediate
  3109. ! domain, switch grid to point to ngrid, invoke feedback_nest_prep, then restore grid
  3110. ! to point to intermediate domain.
  3111. CALL model_to_grid_config_rec ( ngrid%id , model_config_rec , nconfig_flags )
  3112. CALL set_scalar_indices_from_config ( ngrid%id , idum1 , idum2 )
  3113. xgrid => grid
  3114. grid => ngrid
  3115. CALL feedback_nest_prep ( grid, nconfig_flags &
  3116. !
  3117. #include "actual_new_args.inc"
  3118. !
  3119. )
  3120. ! put things back so grid is intermediate grid
  3121. grid => xgrid
  3122. CALL set_scalar_indices_from_config ( grid%id , idum1 , idum2 )
  3123. ! "interp" (basically copy) ngrid onto intermediate grid
  3124. #include "nest_feedbackup_interp.inc"
  3125. RETURN
  3126. END SUBROUTINE feedback_domain_em_part1
  3127. !------------------------------------------------------------------
  3128. SUBROUTINE feedback_domain_em_part2 ( grid, intermediate_grid, ngrid , config_flags &
  3129. !
  3130. #include "dummy_new_args.inc"
  3131. !
  3132. )
  3133. USE module_state_description
  3134. USE module_domain, ONLY : domain, domain_clock_get, get_ijk_from_grid
  3135. USE module_configure, ONLY : grid_config_rec_type, model_config_rec
  3136. USE module_dm, ONLY : ntasks, ntasks_x, ntasks_y, itrace, local_communicator, mytask, &
  3137. ipe_save, jpe_save, ips_save, jps_save, get_dm_max_halo_width
  3138. USE module_comm_nesting_dm, ONLY : halo_interp_up_sub
  3139. USE module_utility
  3140. IMPLICIT NONE
  3141. !
  3142. TYPE(domain), POINTER :: grid ! name of the grid being dereferenced (must be "grid")
  3143. TYPE(domain), POINTER :: intermediate_grid
  3144. TYPE(domain), POINTER :: ngrid
  3145. #include <dummy_new_decl.inc>
  3146. INTEGER nlev, msize
  3147. INTEGER i,j,pig,pjg,cm,cn,nig,njg,retval,k
  3148. TYPE (grid_config_rec_type) :: config_flags
  3149. REAL xv(500)
  3150. INTEGER :: cids, cide, cjds, cjde, ckds, ckde, &
  3151. cims, cime, cjms, cjme, ckms, ckme, &
  3152. cips, cipe, cjps, cjpe, ckps, ckpe
  3153. INTEGER :: nids, nide, njds, njde, nkds, nkde, &
  3154. nims, nime, njms, njme, nkms, nkme, &
  3155. nips, nipe, njps, njpe, nkps, nkpe
  3156. INTEGER :: ids, ide, jds, jde, kds, kde, &
  3157. ims, ime, jms, jme, kms, kme, &
  3158. ips, ipe, jps, jpe, kps, kpe
  3159. INTEGER idim1,idim2,idim3,idim4,idim5,idim6,idim7
  3160. INTEGER icoord, jcoord, idim_cd, jdim_cd
  3161. INTEGER local_comm, myproc, nproc
  3162. INTEGER iparstrt, jparstrt, sw, thisdomain_max_halo_width
  3163. REAL nest_influence
  3164. character*256 :: timestr
  3165. integer ierr
  3166. LOGICAL, EXTERNAL :: cd_feedback_mask
  3167. ! On entry to this routine,
  3168. ! "grid" refers to the parent domain
  3169. ! "intermediate_grid" refers to local copy of parent domain that overlies this patch of nest
  3170. ! "ngrid" refers to the nest, which is only needed for smoothing on the parent because
  3171. ! the nest feedback data has already been transferred during em_nest_feedbackup_interp
  3172. ! in part1, above.
  3173. ! The way these settings c and n dimensions are set, below, looks backwards but from the point
  3174. ! of view of the RSL routine rsl_lite_to_parent_info(), call to which is included by
  3175. ! em_nest_feedbackup_pack, the "n" domain represents the parent domain and the "c" domain
  3176. ! represents the intermediate domain. The backwards lookingness should be fixed in the gen_comms.c
  3177. ! registry routine that accompanies RSL_LITE but, just as it's sometimes easier to put up a road
  3178. ! sign that says "DIP" than fix the dip, at this point it was easier just to write this comment. JM
  3179. !
  3180. nest_influence = 1.
  3181. CALL domain_clock_get( grid, current_timestr=timestr )
  3182. CALL get_ijk_from_grid ( intermediate_grid , &
  3183. cids, cide, cjds, cjde, ckds, ckde, &
  3184. cims, cime, cjms, cjme, ckms, ckme, &
  3185. cips, cipe, cjps, cjpe, ckps, ckpe )
  3186. CALL get_ijk_from_grid ( grid , &
  3187. nids, nide, njds, njde, nkds, nkde, &
  3188. nims, nime, njms, njme, nkms, nkme, &
  3189. nips, nipe, njps, njpe, nkps, nkpe )
  3190. CALL nl_get_i_parent_start ( intermediate_grid%id, iparstrt )
  3191. CALL nl_get_j_parent_start ( intermediate_grid%id, jparstrt )
  3192. CALL nl_get_shw ( intermediate_grid%id, sw )
  3193. icoord = iparstrt - sw
  3194. jcoord = jparstrt - sw
  3195. idim_cd = cide - cids + 1
  3196. jdim_cd = cjde - cjds + 1
  3197. nlev = ckde - ckds + 1
  3198. CALL get_dm_max_halo_width ( grid%id , thisdomain_max_halo_width )
  3199. #include "nest_feedbackup_pack.inc"
  3200. CALL wrf_get_dm_communicator ( local_comm )
  3201. CALL wrf_get_myproc( myproc )
  3202. CALL wrf_get_nproc( nproc )
  3203. CALL rsl_lite_merge_msgs( myproc, nproc, local_comm )
  3204. #define NEST_INFLUENCE(A,B) A = B
  3205. #include "nest_feedbackup_unpack.inc"
  3206. ! smooth coarse grid
  3207. CALL get_ijk_from_grid ( ngrid, &
  3208. nids, nide, njds, njde, nkds, nkde, &
  3209. nims, nime, njms, njme, nkms, nkme, &
  3210. nips, nipe, njps, njpe, nkps, nkpe )
  3211. CALL get_ijk_from_grid ( grid , &
  3212. ids, ide, jds, jde, kds, kde, &
  3213. ims, ime, jms, jme, kms, kme, &
  3214. ips, ipe, jps, jpe, kps, kpe )
  3215. #include "HALO_INTERP_UP.inc"
  3216. CALL get_ijk_from_grid ( grid , &
  3217. cids, cide, cjds, cjde, ckds, ckde, &
  3218. cims, cime, cjms, cjme, ckms, ckme, &
  3219. cips, cipe, cjps, cjpe, ckps, ckpe )
  3220. #include "nest_feedbackup_smooth.inc"
  3221. RETURN
  3222. END SUBROUTINE feedback_domain_em_part2
  3223. #endif
  3224. #if ( NMM_CORE == 1 && NMM_NEST == 1 )
  3225. !==============================================================================
  3226. ! NMM nesting infrastructure extended from EM core. This is gopal's doing.
  3227. !==============================================================================
  3228. SUBROUTINE interp_domain_nmm_part1 ( grid, intermediate_grid, ngrid, config_flags &
  3229. !
  3230. #include "dummy_new_args.inc"
  3231. !
  3232. )
  3233. USE module_state_description
  3234. USE module_domain, ONLY : domain, get_ijk_from_grid
  3235. USE module_configure, ONLY : grid_config_rec_type
  3236. USE module_dm, ONLY : ntasks, ntasks_x, ntasks_y, itrace, local_communicator, mytask, &
  3237. ipe_save, jpe_save, ips_save, jps_save, get_dm_max_halo_width
  3238. USE module_timing
  3239. IMPLICIT NONE
  3240. !
  3241. TYPE(domain), POINTER :: grid ! name of the grid being dereferenced (must be "grid")
  3242. TYPE(domain), POINTER :: intermediate_grid
  3243. TYPE(domain), POINTER :: ngrid
  3244. #include <dummy_new_decl.inc>
  3245. INTEGER nlev, msize
  3246. INTEGER i,j,pig,pjg,cm,cn,nig,njg,retval,k
  3247. INTEGER iparstrt,jparstrt,sw
  3248. TYPE (grid_config_rec_type) :: config_flags
  3249. REAL xv(500)
  3250. INTEGER :: cids, cide, cjds, cjde, ckds, ckde, &
  3251. cims, cime, cjms, cjme, ckms, ckme, &
  3252. cips, cipe, cjps, cjpe, ckps, ckpe
  3253. INTEGER :: iids, iide, ijds, ijde, ikds, ikde, &
  3254. iims, iime, ijms, ijme, ikms, ikme, &
  3255. iips, iipe, ijps, ijpe, ikps, ikpe
  3256. INTEGER :: nids, nide, njds, njde, nkds, nkde, &
  3257. nims, nime, njms, njme, nkms, nkme, &
  3258. nips, nipe, njps, njpe, nkps, nkpe
  3259. INTEGER idim1,idim2,idim3,idim4,idim5,idim6,idim7
  3260. INTEGER icoord, jcoord, idim_cd, jdim_cd, pgr
  3261. INTEGER local_comm, myproc, nproc
  3262. INTEGER thisdomain_max_halo_width
  3263. CALL wrf_get_dm_communicator ( local_comm )
  3264. CALL wrf_get_myproc( myproc )
  3265. CALL wrf_get_nproc( nproc )
  3266. !#define COPY_IN
  3267. !#include <scalar_derefs.inc>
  3268. CALL get_ijk_from_grid ( grid , &
  3269. cids, cide, cjds, cjde, ckds, ckde, &
  3270. cims, cime, cjms, cjme, ckms, ckme, &
  3271. cips, cipe, cjps, cjpe, ckps, ckpe )
  3272. CALL get_ijk_from_grid ( intermediate_grid , &
  3273. iids, iide, ijds, ijde, ikds, ikde, &
  3274. iims, iime, ijms, ijme, ikms, ikme, &
  3275. iips, iipe, ijps, ijpe, ikps, ikpe )
  3276. CALL get_ijk_from_grid ( ngrid , &
  3277. nids, nide, njds, njde, nkds, nkde, &
  3278. nims, nime, njms, njme, nkms, nkme, &
  3279. nips, nipe, njps, njpe, nkps, nkpe )
  3280. CALL nl_get_parent_grid_ratio ( ngrid%id, pgr )
  3281. CALL nl_get_i_parent_start ( intermediate_grid%id, iparstrt )
  3282. CALL nl_get_j_parent_start ( intermediate_grid%id, jparstrt )
  3283. CALL nl_get_shw ( intermediate_grid%id, sw )
  3284. icoord = iparstrt - sw
  3285. jcoord = jparstrt - sw
  3286. idim_cd = iide - iids + 1
  3287. jdim_cd = ijde - ijds + 1
  3288. nlev = ckde - ckds + 1
  3289. CALL get_dm_max_halo_width ( ngrid%id , thisdomain_max_halo_width )
  3290. #include "nest_interpdown_pack.inc"
  3291. CALL rsl_lite_bcast_msgs( myproc, nproc, local_comm )
  3292. !#define COPY_OUT
  3293. !#include <scalar_derefs.inc>
  3294. RETURN
  3295. END SUBROUTINE interp_domain_nmm_part1
  3296. !------------------------------------------------------------------
  3297. SUBROUTINE interp_domain_nmm_part2 ( grid, ngrid, config_flags &
  3298. !
  3299. #include "dummy_new_args.inc"
  3300. !
  3301. )
  3302. USE module_state_description
  3303. USE module_domain, ONLY : domain, get_ijk_from_grid
  3304. USE module_configure, ONLY : grid_config_rec_type
  3305. USE module_dm, ONLY : ntasks, ntasks_x, ntasks_y, itrace, local_communicator, mytask, &
  3306. ipe_save, jpe_save, ips_save, jps_save, get_dm_max_halo_width
  3307. USE module_comm_nesting_dm, ONLY : halo_interp_down_sub
  3308. IMPLICIT NONE
  3309. !
  3310. TYPE(domain), POINTER :: grid ! name of the grid being dereferenced (must be "grid")
  3311. TYPE(domain), POINTER :: ngrid
  3312. #include <dummy_new_decl.inc>
  3313. INTEGER nlev, msize
  3314. INTEGER i,j,pig,pjg,cm,cn,nig,njg,retval,k
  3315. TYPE (grid_config_rec_type) :: config_flags
  3316. REAL xv(500)
  3317. INTEGER :: cids, cide, cjds, cjde, ckds, ckde, &
  3318. cims, cime, cjms, cjme, ckms, ckme, &
  3319. cips, cipe, cjps, cjpe, ckps, ckpe
  3320. INTEGER :: nids, nide, njds, njde, nkds, nkde, &
  3321. nims, nime, njms, njme, nkms, nkme, &
  3322. nips, nipe, njps, njpe, nkps, nkpe
  3323. INTEGER :: ids, ide, jds, jde, kds, kde, &
  3324. ims, ime, jms, jme, kms, kme, &
  3325. ips, ipe, jps, jpe, kps, kpe
  3326. INTEGER idim1,idim2,idim3,idim4,idim5,idim6,idim7
  3327. INTEGER myproc
  3328. INTEGER ierr
  3329. !#ifdef DEREF_KLUDGE
  3330. !! see http://www.mmm.ucar.edu/wrf/WG2/topics/deref_kludge.htm
  3331. ! INTEGER :: sm31 , em31 , sm32 , em32 , sm33 , em33
  3332. ! INTEGER :: sm31x, em31x, sm32x, em32x, sm33x, em33x
  3333. ! INTEGER :: sm31y, em31y, sm32y, em32y, sm33y, em33y
  3334. !#endif
  3335. #include "deref_kludge.h"
  3336. !#define COPY_IN
  3337. !#include <scalar_derefs.inc>
  3338. CALL get_ijk_from_grid ( grid , &
  3339. cids, cide, cjds, cjde, ckds, ckde, &
  3340. cims, cime, cjms, cjme, ckms, ckme, &
  3341. cips, cipe, cjps, cjpe, ckps, ckpe )
  3342. CALL get_ijk_from_grid ( ngrid , &
  3343. nids, nide, njds, njde, nkds, nkde, &
  3344. nims, nime, njms, njme, nkms, nkme, &
  3345. nips, nipe, njps, njpe, nkps, nkpe )
  3346. nlev = ckde - ckds + 1
  3347. #include "nest_interpdown_unpack.inc"
  3348. CALL get_ijk_from_grid ( grid , &
  3349. ids, ide, jds, jde, kds, kde, &
  3350. ims, ime, jms, jme, kms, kme, &
  3351. ips, ipe, jps, jpe, kps, kpe )
  3352. #include "HALO_INTERP_DOWN.inc"
  3353. #include "nest_interpdown_interp.inc"
  3354. !#define COPY_OUT
  3355. !#include <scalar_derefs.inc>
  3356. RETURN
  3357. END SUBROUTINE interp_domain_nmm_part2
  3358. !------------------------------------------------------------------
  3359. SUBROUTINE force_domain_nmm_part1 ( grid, intermediate_grid, config_flags &
  3360. !
  3361. #include "dummy_new_args.inc"
  3362. !
  3363. )
  3364. USE module_state_description
  3365. USE module_domain, ONLY : domain, get_ijk_from_grid
  3366. USE module_configure, ONLY : grid_config_rec_type
  3367. USE module_dm, ONLY : ntasks, ntasks_x, ntasks_y, itrace, local_communicator, mytask, &
  3368. ipe_save, jpe_save, ips_save, jps_save, get_dm_max_halo_width
  3369. USE module_timing
  3370. !
  3371. TYPE(domain), POINTER :: grid ! name of the grid being dereferenced (must be "grid")
  3372. TYPE(domain), POINTER :: intermediate_grid
  3373. #include <dummy_new_decl.inc>
  3374. INTEGER nlev, msize
  3375. INTEGER i,j,pig,pjg,cm,cn,nig,njg,retval,k
  3376. TYPE (grid_config_rec_type) :: config_flags
  3377. REAL xv(500)
  3378. INTEGER :: cids, cide, cjds, cjde, ckds, ckde, &
  3379. cims, cime, cjms, cjme, ckms, ckme, &
  3380. cips, cipe, cjps, cjpe, ckps, ckpe
  3381. INTEGER :: nids, nide, njds, njde, nkds, nkde, &
  3382. nims, nime, njms, njme, nkms, nkme, &
  3383. nips, nipe, njps, njpe, nkps, nkpe
  3384. INTEGER idim1,idim2,idim3,idim4,idim5,idim6,idim7
  3385. !#define COPY_IN
  3386. !#include <scalar_derefs.inc>
  3387. !
  3388. CALL get_ijk_from_grid ( grid , &
  3389. cids, cide, cjds, cjde, ckds, ckde, &
  3390. cims, cime, cjms, cjme, ckms, ckme, &
  3391. cips, cipe, cjps, cjpe, ckps, ckpe )
  3392. CALL get_ijk_from_grid ( intermediate_grid , &
  3393. nids, nide, njds, njde, nkds, nkde, &
  3394. nims, nime, njms, njme, nkms, nkme, &
  3395. nips, nipe, njps, njpe, nkps, nkpe )
  3396. nlev = ckde - ckds + 1
  3397. #include "nest_forcedown_pack.inc"
  3398. ! WRITE(0,*)'I have completed PACKING of BCs data successfully'
  3399. !#define COPY_OUT
  3400. !#include <scalar_derefs.inc>
  3401. RETURN
  3402. END SUBROUTINE force_domain_nmm_part1
  3403. !==============================================================================================
  3404. SUBROUTINE force_domain_nmm_part2 ( grid, ngrid, config_flags &
  3405. !
  3406. #include "dummy_new_args.inc"
  3407. !
  3408. )
  3409. USE module_state_description
  3410. USE module_domain, ONLY : domain, get_ijk_from_grid
  3411. USE module_configure, ONLY : grid_config_rec_type
  3412. USE module_dm, ONLY : ntasks, ntasks_x, ntasks_y, itrace, local_communicator, mytask, &
  3413. ipe_save, jpe_save, ips_save, jps_save, get_dm_max_halo_width
  3414. #ifdef HWRF
  3415. USE module_comm_dm, ONLY : HALO_NMM_FORCE_DOWN1_sub, HALO_NMM_FORCE_DOWN_SST_sub
  3416. #else
  3417. USE module_comm_dm, ONLY : HALO_NMM_FORCE_DOWN1_sub
  3418. #endif
  3419. IMPLICIT NONE
  3420. !
  3421. TYPE(domain), POINTER :: grid ! name of the grid being dereferenced (must be "grid")
  3422. TYPE(domain), POINTER :: ngrid
  3423. #include <dummy_new_decl.inc>
  3424. INTEGER nlev, msize
  3425. INTEGER i,j,pig,pjg,cm,cn,nig,njg,retval,k
  3426. TYPE (grid_config_rec_type) :: config_flags
  3427. REAL xv(500)
  3428. INTEGER :: cids, cide, cjds, cjde, ckds, ckde, &
  3429. cims, cime, cjms, cjme, ckms, ckme, &
  3430. cips, cipe, cjps, cjpe, ckps, ckpe
  3431. INTEGER :: nids, nide, njds, njde, nkds, nkde, &
  3432. nims, nime, njms, njme, nkms, nkme, &
  3433. nips, nipe, njps, njpe, nkps, nkpe
  3434. INTEGER :: ids, ide, jds, jde, kds, kde, &
  3435. ims, ime, jms, jme, kms, kme, &
  3436. ips, ipe, jps, jpe, kps, kpe
  3437. INTEGER idim1,idim2,idim3,idim4,idim5,idim6,idim7
  3438. REAL dummy_xs, dummy_xe, dummy_ys, dummy_ye
  3439. integer myproc
  3440. !#ifdef DEREF_KLUDGE
  3441. !! see http://www.mmm.ucar.edu/wrf/WG2/topics/deref_kludge.htm
  3442. ! INTEGER :: sm31 , em31 , sm32 , em32 , sm33 , em33
  3443. ! INTEGER :: sm31x, em31x, sm32x, em32x, sm33x, em33x
  3444. ! INTEGER :: sm31y, em31y, sm32y, em32y, sm33y, em33y
  3445. !#endif
  3446. #include "deref_kludge.h"
  3447. !#define COPY_IN
  3448. !#include <scalar_derefs.inc>
  3449. CALL get_ijk_from_grid ( grid , &
  3450. cids, cide, cjds, cjde, ckds, ckde, &
  3451. cims, cime, cjms, cjme, ckms, ckme, &
  3452. cips, cipe, cjps, cjpe, ckps, ckpe )
  3453. CALL get_ijk_from_grid ( ngrid , &
  3454. nids, nide, njds, njde, nkds, nkde, &
  3455. nims, nime, njms, njme, nkms, nkme, &
  3456. nips, nipe, njps, njpe, nkps, nkpe )
  3457. nlev = ckde - ckds + 1
  3458. #include "nest_interpdown_unpack.inc"
  3459. CALL get_ijk_from_grid ( grid , &
  3460. ids, ide, jds, jde, kds, kde, &
  3461. ims, ime, jms, jme, kms, kme, &
  3462. ips, ipe, jps, jpe, kps, kpe )
  3463. #ifdef HWRF
  3464. IF(ngrid%force_sst(1) == 1) then
  3465. #include "HALO_NMM_FORCE_DOWN_SST.inc"
  3466. ENDIF
  3467. #endif
  3468. #include "HALO_NMM_FORCE_DOWN1.inc"
  3469. ! code here to interpolate the data into the nested domain
  3470. #include "nest_forcedown_interp.inc"
  3471. !#define COPY_OUT
  3472. !#include <scalar_derefs.inc>
  3473. RETURN
  3474. END SUBROUTINE force_domain_nmm_part2
  3475. !================================================================================
  3476. !
  3477. ! This routine exists only to call a halo on a domain (the nest)
  3478. ! gets called from feedback_domain_em_part1, below. This is needed
  3479. ! because the halo code expects the fields being exchanged to have
  3480. ! been dereferenced from the grid data structure, but in feedback_domain_em_part1
  3481. ! the grid data structure points to the coarse domain, not the nest.
  3482. ! And we want the halo exchange on the nest, so that the code in
  3483. ! em_nest_feedbackup_interp.inc will work correctly on multi-p. JM 20040308
  3484. !
  3485. SUBROUTINE feedback_nest_prep_nmm ( grid, config_flags &
  3486. !
  3487. #include "dummy_new_args.inc"
  3488. !
  3489. )
  3490. USE module_state_description
  3491. USE module_domain, ONLY : domain, get_ijk_from_grid
  3492. USE module_configure, ONLY : grid_config_rec_type
  3493. USE module_dm, ONLY : ntasks, ntasks_x, ntasks_y, itrace, local_communicator, mytask, &
  3494. ipe_save, jpe_save, ips_save, jps_save, get_dm_max_halo_width
  3495. USE module_comm_dm, ONLY : HALO_NMM_WEIGHTS_sub
  3496. IMPLICIT NONE
  3497. !
  3498. TYPE(domain), TARGET :: grid ! name of the grid being dereferenced (must be "grid")
  3499. TYPE (grid_config_rec_type) :: config_flags ! configureation flags, has vertical dim of
  3500. ! soil temp, moisture, etc., has vertical dim
  3501. ! of soil categories
  3502. #include <dummy_new_decl.inc>
  3503. INTEGER :: ids, ide, jds, jde, kds, kde, &
  3504. ims, ime, jms, jme, kms, kme, &
  3505. ips, ipe, jps, jpe, kps, kpe
  3506. INTEGER idim1,idim2,idim3,idim4,idim5,idim6,idim7
  3507. INTEGER :: idum1, idum2
  3508. !#ifdef DEREF_KLUDGE
  3509. !! see http://www.mmm.ucar.edu/wrf/WG2/topics/deref_kludge.htm
  3510. ! INTEGER :: sm31 , em31 , sm32 , em32 , sm33 , em33
  3511. ! INTEGER :: sm31x, em31x, sm32x, em32x, sm33x, em33x
  3512. ! INTEGER :: sm31y, em31y, sm32y, em32y, sm33y, em33y
  3513. !#endif
  3514. #include "deref_kludge.h"
  3515. !#define COPY_IN
  3516. !#include <scalar_derefs.inc>
  3517. CALL get_ijk_from_grid ( grid , &
  3518. ids, ide, jds, jde, kds, kde, &
  3519. ims, ime, jms, jme, kms, kme, &
  3520. ips, ipe, jps, jpe, kps, kpe )
  3521. #ifdef DM_PARALLEL
  3522. #include "HALO_NMM_WEIGHTS.inc"
  3523. #endif
  3524. !#define COPY_OUT
  3525. !#include <scalar_derefs.inc>
  3526. END SUBROUTINE feedback_nest_prep_nmm
  3527. !------------------------------------------------------------------
  3528. SUBROUTINE feedback_domain_nmm_part1 ( grid, ngrid, config_flags &
  3529. !
  3530. #include "dummy_new_args.inc"
  3531. !
  3532. )
  3533. USE module_state_description
  3534. USE module_domain, ONLY : domain, get_ijk_from_grid
  3535. USE module_configure, ONLY : grid_config_rec_type, model_config_rec, model_to_grid_config_rec
  3536. USE module_dm, ONLY : ntasks, ntasks_x, ntasks_y, itrace, local_communicator, mytask, &
  3537. ipe_save, jpe_save, ips_save, jps_save, get_dm_max_halo_width
  3538. IMPLICIT NONE
  3539. !
  3540. TYPE(domain), POINTER :: grid ! name of the grid being dereferenced (must be "grid")
  3541. TYPE(domain), POINTER :: ngrid
  3542. #include <dummy_new_decl.inc>
  3543. INTEGER nlev, msize
  3544. INTEGER i,j,pig,pjg,cm,cn,nig,njg,retval,k
  3545. TYPE(domain), POINTER :: xgrid
  3546. TYPE (grid_config_rec_type) :: config_flags, nconfig_flags
  3547. REAL xv(500)
  3548. INTEGER :: cids, cide, cjds, cjde, ckds, ckde, &
  3549. cims, cime, cjms, cjme, ckms, ckme, &
  3550. cips, cipe, cjps, cjpe, ckps, ckpe
  3551. INTEGER :: nids, nide, njds, njde, nkds, nkde, &
  3552. nims, nime, njms, njme, nkms, nkme, &
  3553. nips, nipe, njps, njpe, nkps, nkpe
  3554. INTEGER idim1,idim2,idim3,idim4,idim5,idim6,idim7
  3555. INTEGER local_comm, myproc, nproc, idum1, idum2
  3556. !#ifdef DEREF_KLUDGE
  3557. !! see http://www.mmm.ucar.edu/wrf/WG2/topics/deref_kludge.htm
  3558. ! INTEGER :: sm31 , em31 , sm32 , em32 , sm33 , em33
  3559. ! INTEGER :: sm31x, em31x, sm32x, em32x, sm33x, em33x
  3560. ! INTEGER :: sm31y, em31y, sm32y, em32y, sm33y, em33y
  3561. !#endif
  3562. INTERFACE
  3563. SUBROUTINE feedback_nest_prep_nmm ( grid, config_flags &
  3564. !
  3565. #include "dummy_new_args.inc"
  3566. !
  3567. )
  3568. USE module_state_description
  3569. USE module_domain, ONLY : domain
  3570. USE module_configure, ONLY : grid_config_rec_type
  3571. !
  3572. TYPE (grid_config_rec_type) :: config_flags
  3573. TYPE(domain), TARGET :: grid
  3574. #include <dummy_new_decl.inc>
  3575. END SUBROUTINE feedback_nest_prep_nmm
  3576. END INTERFACE
  3577. !
  3578. !#define COPY_IN
  3579. !#include <scalar_derefs.inc>
  3580. CALL wrf_get_dm_communicator ( local_comm )
  3581. CALL wrf_get_myproc( myproc )
  3582. CALL wrf_get_nproc( nproc )
  3583. !
  3584. ! intermediate grid
  3585. CALL get_ijk_from_grid ( grid , &
  3586. cids, cide, cjds, cjde, ckds, ckde, &
  3587. cims, cime, cjms, cjme, ckms, ckme, &
  3588. cips, cipe, cjps, cjpe, ckps, ckpe )
  3589. ! nest grid
  3590. CALL get_ijk_from_grid ( ngrid , &
  3591. nids, nide, njds, njde, nkds, nkde, &
  3592. nims, nime, njms, njme, nkms, nkme, &
  3593. nips, nipe, njps, njpe, nkps, nkpe )
  3594. nlev = ckde - ckds + 1
  3595. ips_save = ngrid%i_parent_start ! +1 not used in ipe_save & jpe_save
  3596. jps_save = ngrid%j_parent_start ! because of one extra namelist point
  3597. ipe_save = ngrid%i_parent_start + (nide-nids) / ngrid%parent_grid_ratio
  3598. jpe_save = ngrid%j_parent_start + (njde-njds) / ngrid%parent_grid_ratio
  3599. ! feedback_nest_prep invokes a halo exchange on the ngrid. It is done this way
  3600. ! in a separate routine because the HALOs need the data to be dereference from the
  3601. ! grid data structure and, in this routine, the dereferenced fields are related to
  3602. ! the intermediate domain, not the nest itself. Save the current grid pointer to intermediate
  3603. ! domain, switch grid to point to ngrid, invoke feedback_nest_prep, then restore grid
  3604. ! to point to intermediate domain.
  3605. CALL model_to_grid_config_rec ( ngrid%id , model_config_rec , nconfig_flags )
  3606. CALL set_scalar_indices_from_config ( ngrid%id , idum1 , idum2 )
  3607. xgrid => grid
  3608. grid => ngrid
  3609. #include "deref_kludge.h"
  3610. CALL feedback_nest_prep_nmm ( grid, config_flags &
  3611. !
  3612. #include "actual_new_args.inc"
  3613. !
  3614. )
  3615. ! put things back so grid is intermediate grid
  3616. grid => xgrid
  3617. CALL set_scalar_indices_from_config ( grid%id , idum1 , idum2 )
  3618. ! "interp" (basically copy) ngrid onto intermediate grid
  3619. #include "nest_feedbackup_interp.inc"
  3620. !#define COPY_OUT
  3621. !#include <scalar_derefs.inc>
  3622. RETURN
  3623. END SUBROUTINE feedback_domain_nmm_part1
  3624. !------------------------------------------------------------------
  3625. SUBROUTINE feedback_domain_nmm_part2 ( grid, intermediate_grid, ngrid , config_flags &
  3626. !
  3627. #include "dummy_new_args.inc"
  3628. !
  3629. )
  3630. USE module_state_description
  3631. USE module_domain, ONLY : domain, domain_clock_get, get_ijk_from_grid
  3632. USE module_configure, ONLY : grid_config_rec_type
  3633. USE module_dm, ONLY : get_dm_max_halo_width, ips_save, ipe_save, &
  3634. jps_save, jpe_save, ntasks, mytask, ntasks_x, ntasks_y, &
  3635. local_communicator, itrace
  3636. USE module_comm_nesting_dm, ONLY : halo_interp_up_sub
  3637. USE module_utility
  3638. IMPLICIT NONE
  3639. !
  3640. TYPE(domain), POINTER :: grid ! name of the grid being dereferenced (must be "grid")
  3641. TYPE(domain), POINTER :: intermediate_grid
  3642. TYPE(domain), POINTER :: ngrid
  3643. #include <dummy_new_decl.inc>
  3644. INTEGER nlev, msize
  3645. INTEGER i,j,pig,pjg,cm,cn,nig,njg,retval,k
  3646. TYPE (grid_config_rec_type) :: config_flags
  3647. REAL xv(500)
  3648. INTEGER :: cids, cide, cjds, cjde, ckds, ckde, &
  3649. cims, cime, cjms, cjme, ckms, ckme, &
  3650. cips, cipe, cjps, cjpe, ckps, ckpe
  3651. INTEGER :: nids, nide, njds, njde, nkds, nkde, &
  3652. nims, nime, njms, njme, nkms, nkme, &
  3653. nips, nipe, njps, njpe, nkps, nkpe
  3654. INTEGER :: ids, ide, jds, jde, kds, kde, &
  3655. ims, ime, jms, jme, kms, kme, &
  3656. ips, ipe, jps, jpe, kps, kpe
  3657. INTEGER idim1,idim2,idim3,idim4,idim5,idim6,idim7
  3658. INTEGER icoord, jcoord, idim_cd, jdim_cd
  3659. INTEGER local_comm, myproc, nproc
  3660. INTEGER iparstrt, jparstrt, sw
  3661. INTEGER thisdomain_max_halo_width
  3662. character*256 :: timestr
  3663. integer ierr
  3664. REAL nest_influence
  3665. LOGICAL, EXTERNAL :: cd_feedback_mask
  3666. LOGICAL, EXTERNAL :: cd_feedback_mask_v
  3667. !#define COPY_IN
  3668. !#include <scalar_derefs.inc>
  3669. ! On entry to this routine,
  3670. ! "grid" refers to the parent domain
  3671. ! "intermediate_grid" refers to local copy of parent domain that overlies this patch of nest
  3672. ! "ngrid" refers to the nest, which is only needed for smoothing on the parent because
  3673. ! the nest feedback data has already been transferred during em_nest_feedbackup_interp
  3674. ! in part1, above.
  3675. ! The way these settings c and n dimensions are set, below, looks backwards but from the point
  3676. ! of view of the RSL routine rsl_lite_to_parent_info(), call to which is included by
  3677. ! em_nest_feedbackup_pack, the "n" domain represents the parent domain and the "c" domain
  3678. ! represents the intermediate domain. The backwards lookingness should be fixed in the gen_comms.c
  3679. ! registry routine that accompanies RSL_LITE but, just as it's sometimes easier to put up a road
  3680. ! sign that says "DIP" than fix the dip, at this point it was easier just to write this comment. JM
  3681. !
  3682. nest_influence = 0.5
  3683. #define NEST_INFLUENCE(A,B) A = nest_influence*(B) + (1.0-nest_influence)*(A)
  3684. CALL domain_clock_get( grid, current_timestr=timestr )
  3685. CALL get_ijk_from_grid ( intermediate_grid , &
  3686. cids, cide, cjds, cjde, ckds, ckde, &
  3687. cims, cime, cjms, cjme, ckms, ckme, &
  3688. cips, cipe, cjps, cjpe, ckps, ckpe )
  3689. CALL get_ijk_from_grid ( grid , &
  3690. nids, nide, njds, njde, nkds, nkde, &
  3691. nims, nime, njms, njme, nkms, nkme, &
  3692. nips, nipe, njps, njpe, nkps, nkpe )
  3693. nide = nide - 1 !dusan
  3694. njde = njde - 1 !dusan
  3695. CALL nl_get_i_parent_start ( intermediate_grid%id, iparstrt )
  3696. CALL nl_get_j_parent_start ( intermediate_grid%id, jparstrt )
  3697. CALL nl_get_shw ( intermediate_grid%id, sw )
  3698. icoord = iparstrt - sw
  3699. jcoord = jparstrt - sw
  3700. idim_cd = cide - cids + 1
  3701. jdim_cd = cjde - cjds + 1
  3702. nlev = ckde - ckds + 1
  3703. CALL get_dm_max_halo_width ( ngrid%id , thisdomain_max_halo_width )
  3704. #include "nest_feedbackup_pack.inc"
  3705. CALL wrf_get_dm_communicator ( local_comm )
  3706. CALL wrf_get_myproc( myproc )
  3707. CALL wrf_get_nproc( nproc )
  3708. CALL rsl_lite_merge_msgs( myproc, nproc, local_comm )
  3709. #include "nest_feedbackup_unpack.inc"
  3710. ! smooth coarse grid
  3711. CALL get_ijk_from_grid ( ngrid, &
  3712. nids, nide, njds, njde, nkds, nkde, &
  3713. nims, nime, njms, njme, nkms, nkme, &
  3714. nips, nipe, njps, njpe, nkps, nkpe )
  3715. CALL get_ijk_from_grid ( grid , &
  3716. ids, ide, jds, jde, kds, kde, &
  3717. ims, ime, jms, jme, kms, kme, &
  3718. ips, ipe, jps, jpe, kps, kpe )
  3719. #include "HALO_INTERP_UP.inc"
  3720. CALL get_ijk_from_grid ( grid , &
  3721. cids, cide, cjds, cjde, ckds, ckde, &
  3722. cims, cime, cjms, cjme, ckms, ckme, &
  3723. cips, cipe, cjps, cjpe, ckps, ckpe )
  3724. #include "nest_feedbackup_smooth.inc"
  3725. !#define COPY_OUT
  3726. !#include <scalar_derefs.inc>
  3727. RETURN
  3728. END SUBROUTINE feedback_domain_nmm_part2
  3729. !=================================================================================
  3730. ! End of gopal's doing
  3731. !=================================================================================
  3732. #endif
  3733. !------------------------------------------------------------------
  3734. SUBROUTINE wrf_gatherv_real (Field, field_ofst, &
  3735. my_count , & ! sendcount
  3736. globbuf, glob_ofst , & ! recvbuf
  3737. counts , & ! recvcounts
  3738. displs , & ! displs
  3739. root , & ! root
  3740. communicator , & ! communicator
  3741. ierr )
  3742. USE module_dm, ONLY : getrealmpitype
  3743. IMPLICIT NONE
  3744. INTEGER field_ofst, glob_ofst
  3745. INTEGER my_count, communicator, root, ierr
  3746. INTEGER , DIMENSION(*) :: counts, displs
  3747. REAL, DIMENSION(*) :: Field, globbuf
  3748. #ifndef STUBMPI
  3749. INCLUDE 'mpif.h'
  3750. CALL mpi_gatherv( Field( field_ofst ), & ! sendbuf
  3751. my_count , & ! sendcount
  3752. getrealmpitype() , & ! sendtype
  3753. globbuf( glob_ofst ) , & ! recvbuf
  3754. counts , & ! recvcounts
  3755. displs , & ! displs
  3756. getrealmpitype() , & ! recvtype
  3757. root , & ! root
  3758. communicator , & ! communicator
  3759. ierr )
  3760. #endif
  3761. END SUBROUTINE wrf_gatherv_real
  3762. SUBROUTINE wrf_gatherv_double (Field, field_ofst, &
  3763. my_count , & ! sendcount
  3764. globbuf, glob_ofst , & ! recvbuf
  3765. counts , & ! recvcounts
  3766. displs , & ! displs
  3767. root , & ! root
  3768. communicator , & ! communicator
  3769. ierr )
  3770. ! USE module_dm
  3771. IMPLICIT NONE
  3772. INTEGER field_ofst, glob_ofst
  3773. INTEGER my_count, communicator, root, ierr
  3774. INTEGER , DIMENSION(*) :: counts, displs
  3775. ! this next declaration is REAL, not DOUBLE PRECISION because it will be autopromoted
  3776. ! to double precision by the compiler when WRF is compiled for 8 byte reals. Only reason
  3777. ! for having this separate routine is so we pass the correct MPI type to mpi_scatterv
  3778. ! if we were not indexing the globbuf and Field arrays it would not even matter
  3779. REAL, DIMENSION(*) :: Field, globbuf
  3780. #ifndef STUBMPI
  3781. INCLUDE 'mpif.h'
  3782. CALL mpi_gatherv( Field( field_ofst ), & ! sendbuf
  3783. my_count , & ! sendcount
  3784. MPI_DOUBLE_PRECISION , & ! sendtype
  3785. globbuf( glob_ofst ) , & ! recvbuf
  3786. counts , & ! recvcounts
  3787. displs , & ! displs
  3788. MPI_DOUBLE_PRECISION , & ! recvtype
  3789. root , & ! root
  3790. communicator , & ! communicator
  3791. ierr )
  3792. #endif
  3793. END SUBROUTINE wrf_gatherv_double
  3794. SUBROUTINE wrf_gatherv_integer (Field, field_ofst, &
  3795. my_count , & ! sendcount
  3796. globbuf, glob_ofst , & ! recvbuf
  3797. counts , & ! recvcounts
  3798. displs , & ! displs
  3799. root , & ! root
  3800. communicator , & ! communicator
  3801. ierr )
  3802. IMPLICIT NONE
  3803. INTEGER field_ofst, glob_ofst
  3804. INTEGER my_count, communicator, root, ierr
  3805. INTEGER , DIMENSION(*) :: counts, displs
  3806. INTEGER, DIMENSION(*) :: Field, globbuf
  3807. #ifndef STUBMPI
  3808. INCLUDE 'mpif.h'
  3809. CALL mpi_gatherv( Field( field_ofst ), & ! sendbuf
  3810. my_count , & ! sendcount
  3811. MPI_INTEGER , & ! sendtype
  3812. globbuf( glob_ofst ) , & ! recvbuf
  3813. counts , & ! recvcounts
  3814. displs , & ! displs
  3815. MPI_INTEGER , & ! recvtype
  3816. root , & ! root
  3817. communicator , & ! communicator
  3818. ierr )
  3819. #endif
  3820. END SUBROUTINE wrf_gatherv_integer
  3821. !new stuff 20070124
  3822. SUBROUTINE wrf_scatterv_real ( &
  3823. globbuf, glob_ofst , & ! recvbuf
  3824. counts , & ! recvcounts
  3825. Field, field_ofst, &
  3826. my_count , & ! sendcount
  3827. displs , & ! displs
  3828. root , & ! root
  3829. communicator , & ! communicator
  3830. ierr )
  3831. USE module_dm, ONLY : getrealmpitype
  3832. IMPLICIT NONE
  3833. INTEGER field_ofst, glob_ofst
  3834. INTEGER my_count, communicator, root, ierr
  3835. INTEGER , DIMENSION(*) :: counts, displs
  3836. REAL, DIMENSION(*) :: Field, globbuf
  3837. #ifndef STUBMPI
  3838. INCLUDE 'mpif.h'
  3839. CALL mpi_scatterv( &
  3840. globbuf( glob_ofst ) , & ! recvbuf
  3841. counts , & ! recvcounts
  3842. displs , & ! displs
  3843. getrealmpitype() , & ! recvtype
  3844. Field( field_ofst ), & ! sendbuf
  3845. my_count , & ! sendcount
  3846. getrealmpitype() , & ! sendtype
  3847. root , & ! root
  3848. communicator , & ! communicator
  3849. ierr )
  3850. #endif
  3851. END SUBROUTINE wrf_scatterv_real
  3852. SUBROUTINE wrf_scatterv_double ( &
  3853. globbuf, glob_ofst , & ! recvbuf
  3854. counts , & ! recvcounts
  3855. Field, field_ofst, &
  3856. my_count , & ! sendcount
  3857. displs , & ! displs
  3858. root , & ! root
  3859. communicator , & ! communicator
  3860. ierr )
  3861. IMPLICIT NONE
  3862. INTEGER field_ofst, glob_ofst
  3863. INTEGER my_count, communicator, root, ierr
  3864. INTEGER , DIMENSION(*) :: counts, displs
  3865. REAL, DIMENSION(*) :: Field, globbuf
  3866. #ifndef STUBMPI
  3867. INCLUDE 'mpif.h'
  3868. ! this next declaration is REAL, not DOUBLE PRECISION because it will be autopromoted
  3869. ! to double precision by the compiler when WRF is compiled for 8 byte reals. Only reason
  3870. ! for having this separate routine is so we pass the correct MPI type to mpi_scatterv
  3871. ! if we were not indexing the globbuf and Field arrays it would not even matter
  3872. CALL mpi_scatterv( &
  3873. globbuf( glob_ofst ) , & ! recvbuf
  3874. counts , & ! recvcounts
  3875. displs , & ! displs
  3876. MPI_DOUBLE_PRECISION , & ! recvtype
  3877. Field( field_ofst ), & ! sendbuf
  3878. my_count , & ! sendcount
  3879. MPI_DOUBLE_PRECISION , & ! sendtype
  3880. root , & ! root
  3881. communicator , & ! communicator
  3882. ierr )
  3883. #endif
  3884. END SUBROUTINE wrf_scatterv_double
  3885. SUBROUTINE wrf_scatterv_integer ( &
  3886. globbuf, glob_ofst , & ! recvbuf
  3887. counts , & ! recvcounts
  3888. Field, field_ofst, &
  3889. my_count , & ! sendcount
  3890. displs , & ! displs
  3891. root , & ! root
  3892. communicator , & ! communicator
  3893. ierr )
  3894. IMPLICIT NONE
  3895. INTEGER field_ofst, glob_ofst
  3896. INTEGER my_count, communicator, root, ierr
  3897. INTEGER , DIMENSION(*) :: counts, displs
  3898. INTEGER, DIMENSION(*) :: Field, globbuf
  3899. #ifndef STUBMPI
  3900. INCLUDE 'mpif.h'
  3901. CALL mpi_scatterv( &
  3902. globbuf( glob_ofst ) , & ! recvbuf
  3903. counts , & ! recvcounts
  3904. displs , & ! displs
  3905. MPI_INTEGER , & ! recvtype
  3906. Field( field_ofst ), & ! sendbuf
  3907. my_count , & ! sendcount
  3908. MPI_INTEGER , & ! sendtype
  3909. root , & ! root
  3910. communicator , & ! communicator
  3911. ierr )
  3912. #endif
  3913. END SUBROUTINE wrf_scatterv_integer
  3914. ! end new stuff 20070124
  3915. SUBROUTINE wrf_dm_gatherv ( v, elemsize , km_s, km_e, wordsz )
  3916. IMPLICIT NONE
  3917. INTEGER elemsize, km_s, km_e, wordsz
  3918. REAL v(*)
  3919. IF ( wordsz .EQ. DWORDSIZE ) THEN
  3920. CALL wrf_dm_gatherv_double(v, elemsize , km_s, km_e)
  3921. ELSE
  3922. CALL wrf_dm_gatherv_single(v, elemsize , km_s, km_e)
  3923. ENDIF
  3924. END SUBROUTINE wrf_dm_gatherv
  3925. SUBROUTINE wrf_dm_gatherv_double ( v, elemsize , km_s, km_e )
  3926. IMPLICIT NONE
  3927. INTEGER elemsize, km_s, km_e
  3928. REAL*8 v(0:*)
  3929. #ifndef STUBMPI
  3930. # ifndef USE_MPI_IN_PLACE
  3931. REAL*8 v_local((km_e-km_s+1)*elemsize)
  3932. # endif
  3933. INTEGER, DIMENSION(:), ALLOCATABLE :: recvcounts, displs
  3934. INTEGER send_type, myproc, nproc, local_comm, ierr, i
  3935. INCLUDE 'mpif.h'
  3936. send_type = MPI_DOUBLE_PRECISION
  3937. CALL wrf_get_dm_communicator ( local_comm )
  3938. CALL wrf_get_nproc( nproc )
  3939. CALL wrf_get_myproc( myproc )
  3940. ALLOCATE( recvcounts(nproc), displs(nproc) )
  3941. i = (km_e-km_s+1)*elemsize
  3942. CALL mpi_allgather( i,1,MPI_INTEGER,recvcounts,1,MPI_INTEGER,local_comm,ierr) ;
  3943. i = (km_s)*elemsize
  3944. CALL mpi_allgather( i,1,MPI_INTEGER,displs,1,MPI_INTEGER,local_comm,ierr) ;
  3945. # ifdef USE_MPI_IN_PLACE
  3946. CALL mpi_allgatherv( MPI_IN_PLACE, &
  3947. # else
  3948. DO i = 1,elemsize*(km_e-km_s+1)
  3949. v_local(i) = v(i+elemsize*km_s-1)
  3950. ENDDO
  3951. CALL mpi_allgatherv( v_local, &
  3952. # endif
  3953. (km_e-km_s+1)*elemsize, &
  3954. send_type, &
  3955. v, &
  3956. recvcounts, &
  3957. displs, &
  3958. send_type, &
  3959. local_comm, &
  3960. ierr )
  3961. DEALLOCATE(recvcounts)
  3962. DEALLOCATE(displs)
  3963. #endif
  3964. return
  3965. END SUBROUTINE wrf_dm_gatherv_double
  3966. SUBROUTINE wrf_dm_gatherv_single ( v, elemsize , km_s, km_e )
  3967. IMPLICIT NONE
  3968. INTEGER elemsize, km_s, km_e
  3969. REAL*4 v(0:*)
  3970. #ifndef STUBMPI
  3971. # ifndef USE_MPI_IN_PLACE
  3972. REAL*4 v_local((km_e-km_s+1)*elemsize)
  3973. # endif
  3974. INTEGER, DIMENSION(:), ALLOCATABLE :: recvcounts, displs
  3975. INTEGER send_type, myproc, nproc, local_comm, ierr, i
  3976. INCLUDE 'mpif.h'
  3977. send_type = MPI_REAL
  3978. CALL wrf_get_dm_communicator ( local_comm )
  3979. CALL wrf_get_nproc( nproc )
  3980. CALL wrf_get_myproc( myproc )
  3981. ALLOCATE( recvcounts(nproc), displs(nproc) )
  3982. i = (km_e-km_s+1)*elemsize
  3983. CALL mpi_allgather( i,1,MPI_INTEGER,recvcounts,1,MPI_INTEGER,local_comm,ierr) ;
  3984. i = (km_s)*elemsize
  3985. CALL mpi_allgather( i,1,MPI_INTEGER,displs,1,MPI_INTEGER,local_comm,ierr) ;
  3986. # ifdef USE_MPI_IN_PLACE
  3987. CALL mpi_allgatherv( MPI_IN_PLACE, &
  3988. # else
  3989. DO i = 1,elemsize*(km_e-km_s+1)
  3990. v_local(i) = v(i+elemsize*km_s-1)
  3991. ENDDO
  3992. CALL mpi_allgatherv( v_local, &
  3993. # endif
  3994. (km_e-km_s+1)*elemsize, &
  3995. send_type, &
  3996. v, &
  3997. recvcounts, &
  3998. displs, &
  3999. send_type, &
  4000. local_comm, &
  4001. ierr )
  4002. DEALLOCATE(recvcounts)
  4003. DEALLOCATE(displs)
  4004. #endif
  4005. return
  4006. END SUBROUTINE wrf_dm_gatherv_single
  4007. SUBROUTINE wrf_dm_decomp1d( nt, km_s, km_e )
  4008. IMPLICIT NONE
  4009. INTEGER, INTENT(IN) :: nt
  4010. INTEGER, INTENT(OUT) :: km_s, km_e
  4011. ! local
  4012. INTEGER nn, nnp, na, nb
  4013. INTEGER myproc, nproc
  4014. CALL wrf_get_myproc(myproc)
  4015. CALL wrf_get_nproc(nproc)
  4016. nn = nt / nproc ! min number done by this task
  4017. nnp = nn
  4018. if ( myproc .lt. mod( nt, nproc ) ) nnp = nnp + 1 ! distribute remainder
  4019. na = min( myproc, mod(nt,nproc) ) ! Number of blocks with remainder that precede this one
  4020. nb = max( 0, myproc - na ) ! number of blocks without a remainder that precede this one
  4021. km_s = na * ( nn+1) + nb * nn ! starting iteration for this task
  4022. km_e = km_s + nnp - 1 ! ending iteration for this task
  4023. END SUBROUTINE wrf_dm_decomp1d
  4024. SUBROUTINE wrf_dm_define_comms ( grid )
  4025. USE module_domain, ONLY : domain
  4026. IMPLICIT NONE
  4027. TYPE(domain) , INTENT (INOUT) :: grid
  4028. RETURN
  4029. END SUBROUTINE wrf_dm_define_comms
  4030. SUBROUTINE tfp_message( fname, lno )
  4031. CHARACTER*(*) fname
  4032. INTEGER lno
  4033. CHARACTER*1024 mess
  4034. #ifndef STUBMPI
  4035. WRITE(mess,*)'tfp_message: ',trim(fname),lno
  4036. CALL wrf_message(mess)
  4037. # ifdef ALLOW_OVERDECOMP
  4038. CALL task_for_point_message ! defined in RSL_LITE/task_for_point.c
  4039. # else
  4040. CALL wrf_error_fatal(mess)
  4041. # endif
  4042. #endif
  4043. END SUBROUTINE tfp_message
  4044. SUBROUTINE set_dm_debug
  4045. USE module_dm, ONLY : dm_debug_flag
  4046. IMPLICIT NONE
  4047. dm_debug_flag = .TRUE.
  4048. END SUBROUTINE set_dm_debug
  4049. SUBROUTINE reset_dm_debug
  4050. USE module_dm, ONLY : dm_debug_flag
  4051. IMPLICIT NONE
  4052. dm_debug_flag = .FALSE.
  4053. END SUBROUTINE reset_dm_debug
  4054. SUBROUTINE get_dm_debug ( arg )
  4055. USE module_dm, ONLY : dm_debug_flag
  4056. IMPLICIT NONE
  4057. LOGICAL arg
  4058. arg = dm_debug_flag
  4059. END SUBROUTINE get_dm_debug