FV3 Bundle
block_control.F90
Go to the documentation of this file.
1 !***********************************************************************
2 !* GNU Lesser General Public License
3 !*
4 !* This file is part of the GFDL Flexible Modeling System (FMS).
5 !*
6 !* FMS is free software: you can redistribute it and/or modify it under
7 !* the terms of the GNU Lesser General Public License as published by
8 !* the Free Software Foundation, either version 3 of the License, or (at
9 !* your option) any later version.
10 !*
11 !* FMS is distributed in the hope that it will be useful, but WITHOUT
12 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 !* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 !* for more details.
15 !*
16 !* You should have received a copy of the GNU Lesser General Public
17 !* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
18 !***********************************************************************
19 
20 !> \file
21 !! \brief Contains the \ref block_control_mod module
22 
24 #include <fms_platform.h>
25 
26 use mpp_mod, only: mpp_error, note, warning, fatal
27 use mpp_domains_mod, only: mpp_compute_extent
28 
29  public block_control_type
30 
31  type ix_type
32  integer, dimension(:,:), _allocatable :: ix _null
33  end type ix_type
34 
35  type pk_type
36  integer, dimension(:), _allocatable :: ii _null
37  integer, dimension(:), _allocatable :: jj _null
38  end type pk_type
39 
41  integer :: nx_block, ny_block !< blocking factor using mpp-style decomposition
42  integer :: nblks !< number of blocks cover MPI domain
43  integer :: isc, iec, jsc, jec !< MPI domain global extents
44  integer :: npz !< vertical extent
45  integer, dimension(:), _allocatable :: ibs _null, & !< block extents for mpp-style
46  ibe _null, & !! decompositions
47  jbs _null, &
48  jbe _null
49  type(ix_type), dimension(:), _allocatable :: ix _null !< dereference packed index from global index
50  !--- packed blocking fields
51  integer, dimension(:), _allocatable :: blksz _null !< number of points in each individual block
52  !! blocks are not required to be uniforom in size
53  integer, dimension(:,:), _allocatable :: blkno _null !< dereference block number using global indices
54  integer, dimension(:,:), _allocatable :: ixp _null !< dereference packed index from global indices
55  !! must be used in conjuction with blkno
56  type(pk_type), dimension(:), _allocatable :: index _null !< dereference global indices from
57  !! block/ixp combo
58  end type block_control_type
59 
61 
62 contains
63 
64 !###############################################################################
65 !> \fn define_blocks
66 !!
67 !! \brief Sets up "blocks" used for OpenMP threading of column-based
68 !! calculations using rad_n[x/y]xblock from coupler_nml
69 !!
70 !! <b> Parameters: </b>
71 !!
72 !! \code{.f90}
73 !! character(len=*), intent(in) :: component
74 !! type(block_control_type), intent(inout) :: Block
75 !! integer, intent(in) :: isc, iec, jsc, jec, kpts
76 !! integer, intent(in) :: nx_block, ny_block
77 !! logical, intent(inout) :: message
78 !! \endcode
79 !!
80 !! \param [in] <component>
81 !! \param [inout] <Block>
82 !! \param [in] <isc>
83 !! \param [in] <iec>
84 !! \param [in] <jsc>
85 !! \param [in] <jec>
86 !! \param [in] <kpts>
87 !! \param [in] <nx_block>
88 !! \param [in] <ny_block>
89 !! \param [inout] <message>
90 !!
91  subroutine define_blocks (component, Block, isc, iec, jsc, jec, kpts, &
92  nx_block, ny_block, message)
93  character(len=*), intent(in) :: component
94  type(block_control_type), intent(inout) :: block
95  integer, intent(in) :: isc, iec, jsc, jec, kpts
96  integer, intent(in) :: nx_block, ny_block
97  logical, intent(inout) :: message
98 
99 !-------------------------------------------------------------------------------
100 ! Local variables:
101 ! blocks
102 ! i1
103 ! i2
104 ! j1
105 ! j2
106 ! text
107 ! i
108 ! j
109 ! nblks
110 ! ii
111 ! jj
112 !-------------------------------------------------------------------------------
113 
114  integer :: blocks
115  integer, dimension(nx_block) :: i1, i2
116  integer, dimension(ny_block) :: j1, j2
117  character(len=256) :: text
118  integer :: i, j, nblks, ii, jj
119 
120  if (message) then
121  if ((mod(iec-isc+1,nx_block) .ne. 0) .or. (mod(jec-jsc+1,ny_block) .ne. 0)) then
122  write( text,'(a,a,2i4,a,2i4,a)' ) trim(component),'define_blocks: domain (',&
123  (iec-isc+1), (jec-jsc+1),') is not an even divisor with definition (',&
124  nx_block, ny_block,') - blocks will not be uniform'
125  call mpp_error (warning, trim(text))
126  endif
127  message = .false.
128  endif
129 
130 !--- set up blocks
131  if (iec-isc+1 .lt. nx_block) &
132  call mpp_error(fatal, 'block_control: number of '//trim(component)//.gt.' nxblocks &
133  &number of elements in MPI-domain size')
134  if (jec-jsc+1 .lt. ny_block) &
135  call mpp_error(fatal, 'block_control: number of '//trim(component)//.gt.' nyblocks &
136  &number of elements in MPI-domain size')
137  call mpp_compute_extent(isc,iec,nx_block,i1,i2)
138  call mpp_compute_extent(jsc,jec,ny_block,j1,j2)
139 
140  nblks = nx_block*ny_block
141  block%isc = isc
142  block%iec = iec
143  block%jsc = jsc
144  block%jec = jec
145  block%npz = kpts
146  block%nx_block = nx_block
147  block%ny_block = ny_block
148  block%nblks = nblks
149 
150  if (.not._allocated(block%ibs)) &
151  allocate (block%ibs(nblks), &
152  block%ibe(nblks), &
153  block%jbs(nblks), &
154  block%jbe(nblks), &
155  block%ix(nblks) )
156 
157  blocks=0
158  do j = 1, ny_block
159  do i = 1, nx_block
160  blocks = blocks + 1
161  block%ibs(blocks) = i1(i)
162  block%jbs(blocks) = j1(j)
163  block%ibe(blocks) = i2(i)
164  block%jbe(blocks) = j2(j)
165  allocate(block%ix(blocks)%ix(i1(i):i2(i),j1(j):j2(j)) )
166  ix = 0
167  do jj = j1(j), j2(j)
168  do ii = i1(i), i2(i)
169  ix = ix+1
170  block%ix(blocks)%ix(ii,jj) = ix
171  enddo
172  enddo
173  enddo
174  enddo
175 
176  end subroutine define_blocks
177 
178 
179 
180 !###############################################################################
181 !> \fn define_blocks_packed
182 !!
183 !! \brief Creates and populates a data type which is used for defining the
184 !! sub-blocks of the MPI-domain to enhance OpenMP and memory performance.
185 !! Uses a packed concept
186 !!
187 !! <b> Parameters: </b>
188 !!
189 !! \code{.f90}
190 !! character(len=*), intent(in) :: component
191 !! type(block_control_type), intent(inout) :: Block
192 !! integer, intent(in) :: isc, iec, jsc, jec, kpts
193 !! integer, intent(inout) :: blksz
194 !! logical, intent(inout) :: message
195 !! \endcode
196 !!
197 !! \param [in] <component>
198 !! \param [inout] <Block>
199 !! \param [in] <isc>
200 !! \param [in] <iec>
201 !! \param [in] <jsc>
202 !! \param [in] <jec>
203 !! \param [in] <kpts>
204 !! \param [inout] <blksz>
205 !! \param [inout] <message>
206 !!
207  subroutine define_blocks_packed (component, Block, isc, iec, jsc, jec, &
208  kpts, blksz, message)
209  character(len=*), intent(in) :: component
210  type(block_control_type), intent(inout) :: block
211  integer, intent(in) :: isc, iec, jsc, jec, kpts
212  integer, intent(inout) :: blksz
213  logical, intent(inout) :: message
214 
215 !-------------------------------------------------------------------------------
216 ! Local variables:
217 ! nblks
218 ! lblksz
219 ! tot_pts
220 ! ii
221 ! jj
222 ! nb
223 ! ix
224 ! text
225 !-------------------------------------------------------------------------------
226 
227  integer :: nblks, lblksz, tot_pts, ii, jj, nb, ix
228  character(len=256) :: text
229 
230  tot_pts = (iec - isc + 1) * (jec - jsc + 1)
231  if (blksz < 0) then
232  nblks = 1
233  blksz = tot_pts
234  else
235  if (mod(tot_pts,blksz) .eq. 0) then
236  nblks = tot_pts/blksz
237  else
238  nblks = ceiling(real(tot_pts)/real(blksz))
239  endif
240  endif
241 
242  if (message) then
243  if (mod(tot_pts,blksz) .ne. 0) then
244  write( text,'(a,a,2i4,a,i4,a,i4)' ) trim(component),'define_blocks_packed: domain (',&
245  (iec-isc+1), (jec-jsc+1),') is not an even divisor with definition (',&
246  blksz,') - blocks will not be uniform with a remainder of ',mod(tot_pts,blksz)
247  call mpp_error (warning, trim(text))
248  endif
249  message = .false.
250  endif
251 
252  block%isc = isc
253  block%iec = iec
254  block%jsc = jsc
255  block%jec = jec
256  block%npz = kpts
257  block%nblks = nblks
258  if (.not. _allocated(block%blksz)) &
259  allocate (block%blksz(nblks), &
260  block%index(nblks), &
261  block%blkno(isc:iec,jsc:jec), &
262  block%ixp(isc:iec,jsc:jec))
263 
264 !--- set up blocks
265  do nb = 1, nblks
266  lblksz = blksz
267  if (nb .EQ. nblks) lblksz = tot_pts - (nb-1) * blksz
268  block%blksz(nb) = lblksz
269  allocate (block%index(nb)%ii(lblksz), &
270  block%index(nb)%jj(lblksz))
271  enddo
272 
273 !--- set up packed indices
274  nb = 1
275  ix = 0
276  do jj = jsc, jec
277  do ii = isc, iec
278  ix = ix + 1
279  if (ix .GT. blksz) then
280  ix = 1
281  nb = nb + 1
282  endif
283  block%ixp(ii,jj) = ix
284  block%blkno(ii,jj) = nb
285  block%index(nb)%ii(ix) = ii
286  block%index(nb)%jj(ix) = jj
287  enddo
288  enddo
289 
290  end subroutine define_blocks_packed
291 
292 end module block_control_mod
Definition: mpp.F90:39
subroutine, public define_blocks(component, Block, isc, iec, jsc, jec, kpts, nx_block, ny_block, message)
subroutine, public define_blocks_packed(component, Block, isc, iec, jsc, jec, kpts, blksz, message)