FMS 2025.01-dev
Flexible Modeling System
Loading...
Searching...
No Matches
block_control.F90
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!> @defgroup block_control_mod block_control_mod
20!> @ingroup block_control
21!> @brief Routines for "blocks" used for OpenMP threading of column-based
22!! calculations
23
24module block_control_mod
25
26use mpp_mod, only: mpp_error, note, warning, fatal, mpp_sum, mpp_npes
27use mpp_domains_mod, only: mpp_compute_extent
28use fms_string_utils_mod, only: string
29implicit none
30
32
33!> Type to dereference packed index from global index.
34!> @ingroup block_control_mod
35type :: ix_type
36 integer, dimension(:,:), allocatable :: ix
37end type ix_type
38
39!> Type to dereference packed index from global indices.
40!> @ingroup block_control_mod
41type :: pk_type
42 integer, dimension(:), allocatable :: ii
43 integer, dimension(:), allocatable :: jj
44end type pk_type
45
46!> @brief Block data and extents for OpenMP threading of column-based calculations
47!> @ingroup block_control_mod
49 integer :: nx_block, ny_block !< blocking factor using mpp-style decomposition
50 integer :: nblks !< number of blocks cover MPI domain
51 integer :: isc, iec, jsc, jec !< MPI domain global extents
52 integer :: npz !< vertical extent
53 integer, dimension(:), allocatable :: ibs , & !< block extents for mpp-style
54 ibe , & !! decompositions
55 jbs , &
56 jbe
57 type(ix_type), dimension(:), allocatable :: ix !< dereference packed index from global index
58 !--- packed blocking fields
59 integer, dimension(:), allocatable :: blksz !< number of points in each individual block
60 !! blocks are not required to be uniforom in size
61 integer, dimension(:,:), allocatable :: blkno !< dereference block number using global indices
62 integer, dimension(:,:), allocatable :: ixp !< dereference packed index from global indices
63 !! must be used in conjuction with blkno
64 type(pk_type), dimension(:), allocatable :: index !< dereference global indices from
65 !! block/ixp combo
66end type block_control_type
67
68!> @addtogroup block_control_mod
69!> @{
70
72
73contains
74
75!###############################################################################
76!> @brief Sets up "blocks" used for OpenMP threading of column-based
77!! calculations using rad_n[x/y]xblock from coupler_nml
78!!
79 subroutine define_blocks (component, Block, isc, iec, jsc, jec, kpts, &
80 nx_block, ny_block, message)
81 character(len=*), intent(in) :: component !< Component name string
82 type(block_control_type), intent(inout) :: block !< Returns instantiated @ref block_control_type
83 integer, intent(in) :: isc, iec, jsc, jec, kpts
84 integer, intent(in) :: nx_block, ny_block
85 logical, intent(inout) :: message !< flag for outputting debug message
86
87!-------------------------------------------------------------------------------
88! Local variables:
89! blocks
90! i1
91! i2
92! j1
93! j2
94! text
95! i
96! j
97! nblks
98! ix
99! ii
100! jj
101!-------------------------------------------------------------------------------
102
103 integer :: blocks
104 integer, dimension(nx_block) :: i1, i2
105 integer, dimension(ny_block) :: j1, j2
106 character(len=256) :: text
107 integer :: i, j, nblks, ix, ii, jj
108 integer :: non_uniform_blocks !< Number of non uniform blocks
109
110 if (message) then
111 non_uniform_blocks = 0
112 if ((mod(iec-isc+1,nx_block) .ne. 0) .or. (mod(jec-jsc+1,ny_block) .ne. 0)) then
113 non_uniform_blocks = 1
114 endif
115 call mpp_sum(non_uniform_blocks)
116 if (non_uniform_blocks > 0 ) then
117 call mpp_error(note, string(non_uniform_blocks)//" out of "//string(mpp_npes())//" total domains "//&
118 "have non-uniform blocks for block size ("//string(nx_block)//","//string(ny_block)//")")
119 message = .false.
120 endif
121 endif
122
123!--- set up blocks
124 if (iec-isc+1 .lt. nx_block) &
125 call mpp_error(fatal, 'block_control: number of '//trim(component)//.gt.' nxblocks &
126 &number of elements in MPI-domain size')
127 if (jec-jsc+1 .lt. ny_block) &
128 call mpp_error(fatal, 'block_control: number of '//trim(component)//.gt.' nyblocks &
129 &number of elements in MPI-domain size')
130 call mpp_compute_extent(isc,iec,nx_block,i1,i2)
131 call mpp_compute_extent(jsc,jec,ny_block,j1,j2)
132
133 nblks = nx_block*ny_block
134 block%isc = isc
135 block%iec = iec
136 block%jsc = jsc
137 block%jec = jec
138 block%npz = kpts
139 block%nx_block = nx_block
140 block%ny_block = ny_block
141 block%nblks = nblks
142
143 if (.not.allocated(block%ibs)) &
144 allocate (block%ibs(nblks), &
145 block%ibe(nblks), &
146 block%jbs(nblks), &
147 block%jbe(nblks), &
148 block%ix(nblks) )
149
150 blocks=0
151 do j = 1, ny_block
152 do i = 1, nx_block
153 blocks = blocks + 1
154 block%ibs(blocks) = i1(i)
155 block%jbs(blocks) = j1(j)
156 block%ibe(blocks) = i2(i)
157 block%jbe(blocks) = j2(j)
158 allocate(block%ix(blocks)%ix(i1(i):i2(i),j1(j):j2(j)) )
159 ix = 0
160 do jj = j1(j), j2(j)
161 do ii = i1(i), i2(i)
162 ix = ix+1
163 block%ix(blocks)%ix(ii,jj) = ix
164 enddo
165 enddo
166 enddo
167 enddo
168
169 end subroutine define_blocks
170
171
172
173!###############################################################################
174!> @brief Creates and populates a data type which is used for defining the
175!! sub-blocks of the MPI-domain to enhance OpenMP and memory performance.
176!! Uses a packed concept.
177!!
178 subroutine define_blocks_packed (component, Block, isc, iec, jsc, jec, &
179 kpts, blksz, message)
180 character(len=*), intent(in) :: component !< Component name string
181 type(block_control_type), intent(inout) :: block !< Returns instantiated @ref block_control_type
182 integer, intent(in) :: isc, iec, jsc, jec, kpts
183 integer, intent(inout) :: blksz !< block size
184 logical, intent(inout) :: message !< flag for outputting debug message
185
186!-------------------------------------------------------------------------------
187! Local variables:
188! nblks
189! lblksz
190! tot_pts
191! nb
192! ix
193! ii
194! jj
195! text
196!-------------------------------------------------------------------------------
197
198 integer :: nblks, lblksz, tot_pts, nb, ix, ii, jj
199 character(len=256) :: text
200
201 tot_pts = (iec - isc + 1) * (jec - jsc + 1)
202 if (blksz < 0) then
203 nblks = 1
204 blksz = tot_pts
205 else
206 nblks = tot_pts/blksz
207 if (mod(tot_pts,blksz) .gt. 0) then
208 nblks = nblks + 1
209 endif
210 endif
211
212 if (message) then
213 if (mod(tot_pts,blksz) .ne. 0) then
214 write( text,'(a,a,2i4,a,i4,a,i4)' ) trim(component),'define_blocks_packed: domain (',&
215 (iec-isc+1), (jec-jsc+1),') is not an even divisor with definition (',&
216 blksz,') - blocks will not be uniform with a remainder of ',mod(tot_pts,blksz)
217 call mpp_error (warning, trim(text))
218 endif
219 message = .false.
220 endif
221
222 block%isc = isc
223 block%iec = iec
224 block%jsc = jsc
225 block%jec = jec
226 block%npz = kpts
227 block%nblks = nblks
228 if (.not. allocated(block%blksz)) &
229 allocate (block%blksz(nblks), &
230 block%index(nblks), &
231 block%blkno(isc:iec,jsc:jec), &
232 block%ixp(isc:iec,jsc:jec))
233
234!--- set up blocks
235 do nb = 1, nblks
236 lblksz = blksz
237 if (nb .EQ. nblks) lblksz = tot_pts - (nb-1) * blksz
238 block%blksz(nb) = lblksz
239 allocate (block%index(nb)%ii(lblksz), &
240 block%index(nb)%jj(lblksz))
241 enddo
242
243!--- set up packed indices
244 nb = 1
245 ix = 0
246 do jj = jsc, jec
247 do ii = isc, iec
248 ix = ix + 1
249 if (ix .GT. blksz) then
250 ix = 1
251 nb = nb + 1
252 endif
253 block%ixp(ii,jj) = ix
254 block%blkno(ii,jj) = nb
255 block%index(nb)%ii(ix) = ii
256 block%index(nb)%jj(ix) = jj
257 enddo
258 enddo
259
260 end subroutine define_blocks_packed
261
262end module block_control_mod
263!> @}
264! close documentation grouping
subroutine, public define_blocks(component, block, isc, iec, jsc, jec, kpts, nx_block, ny_block, message)
Sets up "blocks" used for OpenMP threading of column-based calculations using rad_n[x/y]xblock from c...
subroutine, public define_blocks_packed(component, block, isc, iec, jsc, jec, kpts, blksz, message)
Creates and populates a data type which is used for defining the sub-blocks of the MPI-domain to enha...
Block data and extents for OpenMP threading of column-based calculations.
Type to dereference packed index from global index.
Type to dereference packed index from global indices.
character(:) function, allocatable, public string(v, fmt)
Converts a number or a Boolean value to a string.
subroutine mpp_compute_extent(isg, ieg, ndivs, ibegin, iend, extent)
Computes extents for a grid decomposition with the given indices and divisions.
Error handler.
Definition mpp.F90:382
Reduction operation.
Definition mpp.F90:597