130 ncol_global, nrow_block, ncol_block, descriptor, first_p_pos, &
131 local_leading_dimension, template_fmstruct, square_blocks, force_block)
135 INTEGER,
INTENT(in),
OPTIONAL :: nrow_global, ncol_global
136 INTEGER,
INTENT(in),
OPTIONAL :: nrow_block, ncol_block
137 INTEGER,
INTENT(in),
OPTIONAL :: local_leading_dimension
139 INTEGER,
DIMENSION(9),
INTENT(in),
OPTIONAL :: descriptor
140 INTEGER,
OPTIONAL,
DIMENSION(2) :: first_p_pos
142 LOGICAL,
OPTIONAL,
INTENT(in) :: square_blocks
143 LOGICAL,
OPTIONAL,
INTENT(in) :: force_block
145 INTEGER :: i, nmax_block, vlen
146#if defined(__parallel)
147 INTEGER :: iunit, stat
148 INTEGER,
EXTERNAL :: numroc
152 LOGICAL :: my_square_blocks, my_force_block
156 IF (.NOT.
PRESENT(template_fmstruct))
THEN
157 cpassert(
PRESENT(context))
158 cpassert(
PRESENT(nrow_global))
159 cpassert(
PRESENT(ncol_global))
160 fmstruct%local_leading_dimension = 1
161 fmstruct%nrow_block = 0
162 fmstruct%ncol_block = 0
164 fmstruct%context => template_fmstruct%context
165 fmstruct%para_env => template_fmstruct%para_env
166 fmstruct%descriptor = template_fmstruct%descriptor
167 fmstruct%nrow_block = template_fmstruct%nrow_block
168 fmstruct%nrow_global = template_fmstruct%nrow_global
169 fmstruct%ncol_block = template_fmstruct%ncol_block
170 fmstruct%ncol_global = template_fmstruct%ncol_global
171 fmstruct%first_p_pos = template_fmstruct%first_p_pos
172 fmstruct%local_leading_dimension = &
173 template_fmstruct%local_leading_dimension
177 IF (
PRESENT(nrow_block)) fmstruct%nrow_block = nrow_block
178 IF (
PRESENT(ncol_block)) fmstruct%ncol_block = ncol_block
179 IF (0 >= fmstruct%nrow_block)
THEN
180 fmstruct%nrow_block = optimal_blacs_row_block_size
182 IF (0 >= fmstruct%ncol_block)
THEN
183 fmstruct%ncol_block = optimal_blacs_col_block_size
185 cpassert(0 < fmstruct%nrow_block .AND. 0 < fmstruct%ncol_block)
187 IF (
PRESENT(context))
THEN
188 fmstruct%context => context
189 fmstruct%para_env => context%para_env
191 IF (
PRESENT(para_env)) fmstruct%para_env => para_env
192 CALL fmstruct%context%retain()
193 CALL fmstruct%para_env%retain()
195 IF (
PRESENT(nrow_global))
THEN
196 fmstruct%nrow_global = nrow_global
197 fmstruct%local_leading_dimension = 1
199 IF (
PRESENT(ncol_global))
THEN
200 fmstruct%ncol_global = ncol_global
203 my_force_block = force_block_size
204 IF (
PRESENT(force_block)) my_force_block = force_block
205 IF (.NOT. my_force_block)
THEN
207 nmax_block = (fmstruct%nrow_global + fmstruct%context%num_pe(1) - 1)/ &
208 (fmstruct%context%num_pe(1))
210 fmstruct%nrow_block = fmstruct%nrow_block/vlen*vlen
211 nmax_block = nmax_block/vlen*vlen
213 fmstruct%nrow_block = max(min(fmstruct%nrow_block, nmax_block), 1)
215 nmax_block = (fmstruct%ncol_global + fmstruct%context%num_pe(2) - 1)/ &
216 (fmstruct%context%num_pe(2))
218 fmstruct%ncol_block = fmstruct%ncol_block/vlen*vlen
219 nmax_block = nmax_block/vlen*vlen
221 fmstruct%ncol_block = max(min(fmstruct%ncol_block, nmax_block), 1)
225 my_square_blocks = fmstruct%nrow_global == fmstruct%ncol_global
227 IF (
PRESENT(square_blocks)) my_square_blocks = square_blocks
228 IF (my_square_blocks)
THEN
229 fmstruct%nrow_block = min(fmstruct%nrow_block, fmstruct%ncol_block)
230 fmstruct%ncol_block = fmstruct%nrow_block
233 ALLOCATE (fmstruct%nrow_locals(0:(fmstruct%context%num_pe(1) - 1)), &
234 fmstruct%ncol_locals(0:(fmstruct%context%num_pe(2) - 1)))
235 IF (.NOT.
PRESENT(template_fmstruct))
THEN
236 fmstruct%first_p_pos = [0, 0]
238 IF (
PRESENT(first_p_pos)) fmstruct%first_p_pos = first_p_pos
240 fmstruct%nrow_locals = 0
241 fmstruct%ncol_locals = 0
242#if defined(__parallel)
243 fmstruct%nrow_locals(fmstruct%context%mepos(1)) = &
244 numroc(fmstruct%nrow_global, fmstruct%nrow_block, &
245 fmstruct%context%mepos(1), fmstruct%first_p_pos(1), &
246 fmstruct%context%num_pe(1))
247 fmstruct%ncol_locals(fmstruct%context%mepos(2)) = &
248 numroc(fmstruct%ncol_global, fmstruct%ncol_block, &
249 fmstruct%context%mepos(2), fmstruct%first_p_pos(2), &
250 fmstruct%context%num_pe(2))
251 CALL fmstruct%para_env%sum(fmstruct%nrow_locals)
252 CALL fmstruct%para_env%sum(fmstruct%ncol_locals)
253 fmstruct%nrow_locals(:) = fmstruct%nrow_locals(:)/fmstruct%context%num_pe(2)
254 fmstruct%ncol_locals(:) = fmstruct%ncol_locals(:)/fmstruct%context%num_pe(1)
256 IF (sum(fmstruct%ncol_locals) /= fmstruct%ncol_global .OR. &
257 sum(fmstruct%nrow_locals) /= fmstruct%nrow_global)
THEN
262 WRITE (iunit, *)
"mepos", fmstruct%context%mepos(1:2),
"numpe", fmstruct%context%num_pe(1:2)
263 WRITE (iunit, *)
"ncol_global", fmstruct%ncol_global
264 WRITE (iunit, *)
"nrow_global", fmstruct%nrow_global
265 WRITE (iunit, *)
"ncol_locals", fmstruct%ncol_locals
266 WRITE (iunit, *)
"nrow_locals", fmstruct%nrow_locals
270 IF (sum(fmstruct%ncol_locals) /= fmstruct%ncol_global)
THEN
271 cpabort(
"sum of local cols not equal global cols")
273 IF (sum(fmstruct%nrow_locals) /= fmstruct%nrow_global)
THEN
274 cpabort(
"sum of local row not equal global rows")
278 fmstruct%nrow_block = fmstruct%nrow_global
279 fmstruct%ncol_block = fmstruct%ncol_global
280 fmstruct%nrow_locals(fmstruct%context%mepos(1)) = fmstruct%nrow_global
281 fmstruct%ncol_locals(fmstruct%context%mepos(2)) = fmstruct%ncol_global
284 fmstruct%local_leading_dimension = max(fmstruct%local_leading_dimension, &
285 fmstruct%nrow_locals(fmstruct%context%mepos(1)))
286 IF (
PRESENT(local_leading_dimension))
THEN
287 IF (max(1, fmstruct%nrow_locals(fmstruct%context%mepos(1))) > local_leading_dimension)
THEN
288 CALL cp_abort(__location__,
"local_leading_dimension too small ("// &
292 fmstruct%local_leading_dimension = local_leading_dimension
295 NULLIFY (fmstruct%row_indices, fmstruct%col_indices)
298 ALLOCATE (fmstruct%row_indices(max(fmstruct%nrow_locals(fmstruct%context%mepos(1)), 1)))
299 DO i = 1,
SIZE(fmstruct%row_indices)
301 fmstruct%row_indices(i) = fmstruct%l2g_row(i, fmstruct%context%mepos(1))
303 fmstruct%row_indices(i) = i
306 ALLOCATE (fmstruct%col_indices(max(fmstruct%ncol_locals(fmstruct%context%mepos(2)), 1)))
307 DO i = 1,
SIZE(fmstruct%col_indices)
309 fmstruct%col_indices(i) = fmstruct%l2g_col(i, fmstruct%context%mepos(2))
311 fmstruct%col_indices(i) = i
315 fmstruct%ref_count = 1
317 IF (
PRESENT(descriptor))
THEN
318 fmstruct%descriptor = descriptor
320 fmstruct%descriptor = 0
321#if defined(__parallel)
323 CALL descinit(fmstruct%descriptor, fmstruct%nrow_global, &
324 fmstruct%ncol_global, fmstruct%nrow_block, &
325 fmstruct%ncol_block, fmstruct%first_p_pos(1), &
326 fmstruct%first_p_pos(2), fmstruct%context, &
327 fmstruct%local_leading_dimension, stat)
440 descriptor, ncol_block, nrow_block, nrow_global, &
441 ncol_global, first_p_pos, row_indices, &
442 col_indices, nrow_local, ncol_local, nrow_locals, ncol_locals, &
443 local_leading_dimension)
447 INTEGER,
DIMENSION(9),
INTENT(OUT),
OPTIONAL :: descriptor
448 INTEGER,
INTENT(out),
OPTIONAL :: ncol_block, nrow_block, nrow_global, &
450 INTEGER,
DIMENSION(2),
INTENT(out),
OPTIONAL :: first_p_pos
451 INTEGER,
DIMENSION(:),
OPTIONAL,
POINTER :: row_indices, col_indices
452 INTEGER,
INTENT(out),
OPTIONAL :: nrow_local, ncol_local
453 INTEGER,
DIMENSION(:),
OPTIONAL,
POINTER :: nrow_locals, ncol_locals
454 INTEGER,
INTENT(out),
OPTIONAL :: local_leading_dimension
456 IF (
PRESENT(para_env)) para_env => fmstruct%para_env
457 IF (
PRESENT(context)) context => fmstruct%context
458 IF (
PRESENT(descriptor)) descriptor = fmstruct%descriptor
459 IF (
PRESENT(ncol_block)) ncol_block = fmstruct%ncol_block
460 IF (
PRESENT(nrow_block)) nrow_block = fmstruct%nrow_block
461 IF (
PRESENT(nrow_global)) nrow_global = fmstruct%nrow_global
462 IF (
PRESENT(ncol_global)) ncol_global = fmstruct%ncol_global
463 IF (
PRESENT(first_p_pos)) first_p_pos = fmstruct%first_p_pos
464 IF (
PRESENT(nrow_locals)) nrow_locals => fmstruct%nrow_locals
465 IF (
PRESENT(ncol_locals)) ncol_locals => fmstruct%ncol_locals
466 IF (
PRESENT(local_leading_dimension)) local_leading_dimension = &
467 fmstruct%local_leading_dimension
469 IF (
PRESENT(nrow_local)) nrow_local = fmstruct%nrow_locals(fmstruct%context%mepos(1))
470 IF (
PRESENT(ncol_local)) ncol_local = fmstruct%ncol_locals(fmstruct%context%mepos(2))
472 IF (
PRESENT(row_indices)) row_indices => fmstruct%row_indices
473 IF (
PRESENT(col_indices)) col_indices => fmstruct%col_indices
530 LOGICAL,
INTENT(in) :: col, row
532 INTEGER :: n_doubled_items_in_partially_filled_block, ncol_block, ncol_global, newdim_col, &
533 newdim_row, nfilled_blocks, nfilled_blocks_remain, nprocs_col, nprocs_row, nrow_block, &
538 ncol_global=ncol_global, nrow_block=nrow_block, &
539 ncol_block=ncol_block)
540 newdim_row = nrow_global
541 newdim_col = ncol_global
542 nprocs_row = context%num_pe(1)
543 nprocs_col = context%num_pe(2)
544 para_env => struct%para_env
547 IF (ncol_global == 0)
THEN
557 n_doubled_items_in_partially_filled_block = 2*mod(ncol_global, ncol_block)
558 nfilled_blocks = ncol_global/ncol_block
559 nfilled_blocks_remain = mod(nfilled_blocks, nprocs_col)
560 newdim_col = 2*(nfilled_blocks/nprocs_col)
561 IF (n_doubled_items_in_partially_filled_block > ncol_block)
THEN
568 newdim_col = newdim_col + 1
571 n_doubled_items_in_partially_filled_block = n_doubled_items_in_partially_filled_block - ncol_block
572 ELSE IF (nfilled_blocks_remain > 0)
THEN
577 newdim_col = newdim_col + 1
578 n_doubled_items_in_partially_filled_block = 0
581 newdim_col = (newdim_col*nprocs_col + nfilled_blocks_remain)*ncol_block + n_doubled_items_in_partially_filled_block
586 IF (nrow_global == 0)
THEN
589 n_doubled_items_in_partially_filled_block = 2*mod(nrow_global, nrow_block)
590 nfilled_blocks = nrow_global/nrow_block
591 nfilled_blocks_remain = mod(nfilled_blocks, nprocs_row)
592 newdim_row = 2*(nfilled_blocks/nprocs_row)
593 IF (n_doubled_items_in_partially_filled_block > nrow_block)
THEN
594 newdim_row = newdim_row + 1
595 n_doubled_items_in_partially_filled_block = n_doubled_items_in_partially_filled_block - nrow_block
596 ELSE IF (nfilled_blocks_remain > 0)
THEN
597 newdim_row = newdim_row + 1
598 n_doubled_items_in_partially_filled_block = 0
601 newdim_row = (newdim_row*nprocs_row + nfilled_blocks_remain)*nrow_block + n_doubled_items_in_partially_filled_block
609 nrow_global=newdim_row, &
610 ncol_global=newdim_col, &
611 ncol_block=ncol_block, &
612 nrow_block=nrow_block, &
613 square_blocks=.false.)