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)) &
236 fmstruct%first_p_pos = (/0, 0/)
237 IF (
PRESENT(first_p_pos)) fmstruct%first_p_pos = first_p_pos
239 fmstruct%nrow_locals = 0
240 fmstruct%ncol_locals = 0
241#if defined(__parallel)
242 fmstruct%nrow_locals(fmstruct%context%mepos(1)) = &
243 numroc(fmstruct%nrow_global, fmstruct%nrow_block, &
244 fmstruct%context%mepos(1), fmstruct%first_p_pos(1), &
245 fmstruct%context%num_pe(1))
246 fmstruct%ncol_locals(fmstruct%context%mepos(2)) = &
247 numroc(fmstruct%ncol_global, fmstruct%ncol_block, &
248 fmstruct%context%mepos(2), fmstruct%first_p_pos(2), &
249 fmstruct%context%num_pe(2))
250 CALL fmstruct%para_env%sum(fmstruct%nrow_locals)
251 CALL fmstruct%para_env%sum(fmstruct%ncol_locals)
252 fmstruct%nrow_locals(:) = fmstruct%nrow_locals(:)/fmstruct%context%num_pe(2)
253 fmstruct%ncol_locals(:) = fmstruct%ncol_locals(:)/fmstruct%context%num_pe(1)
255 IF (sum(fmstruct%ncol_locals) .NE. fmstruct%ncol_global .OR. &
256 sum(fmstruct%nrow_locals) .NE. fmstruct%nrow_global)
THEN
261 WRITE (iunit, *)
"mepos", fmstruct%context%mepos(1:2),
"numpe", fmstruct%context%num_pe(1:2)
262 WRITE (iunit, *)
"ncol_global", fmstruct%ncol_global
263 WRITE (iunit, *)
"nrow_global", fmstruct%nrow_global
264 WRITE (iunit, *)
"ncol_locals", fmstruct%ncol_locals
265 WRITE (iunit, *)
"nrow_locals", fmstruct%nrow_locals
269 IF (sum(fmstruct%ncol_locals) .NE. fmstruct%ncol_global) &
270 cpabort(
"sum of local cols not equal global cols")
271 IF (sum(fmstruct%nrow_locals) .NE. fmstruct%nrow_global) &
272 cpabort(
"sum of local row not equal global rows")
275 fmstruct%nrow_block = fmstruct%nrow_global
276 fmstruct%ncol_block = fmstruct%ncol_global
277 fmstruct%nrow_locals(fmstruct%context%mepos(1)) = fmstruct%nrow_global
278 fmstruct%ncol_locals(fmstruct%context%mepos(2)) = fmstruct%ncol_global
281 fmstruct%local_leading_dimension = max(fmstruct%local_leading_dimension, &
282 fmstruct%nrow_locals(fmstruct%context%mepos(1)))
283 IF (
PRESENT(local_leading_dimension))
THEN
284 IF (max(1, fmstruct%nrow_locals(fmstruct%context%mepos(1))) > local_leading_dimension) &
285 CALL cp_abort(__location__,
"local_leading_dimension too small ("// &
288 fmstruct%local_leading_dimension = local_leading_dimension
291 NULLIFY (fmstruct%row_indices, fmstruct%col_indices)
294 ALLOCATE (fmstruct%row_indices(max(fmstruct%nrow_locals(fmstruct%context%mepos(1)), 1)))
295 DO i = 1,
SIZE(fmstruct%row_indices)
297 fmstruct%row_indices(i) = fmstruct%l2g_row(i, fmstruct%context%mepos(1))
299 fmstruct%row_indices(i) = i
302 ALLOCATE (fmstruct%col_indices(max(fmstruct%ncol_locals(fmstruct%context%mepos(2)), 1)))
303 DO i = 1,
SIZE(fmstruct%col_indices)
305 fmstruct%col_indices(i) = fmstruct%l2g_col(i, fmstruct%context%mepos(2))
307 fmstruct%col_indices(i) = i
311 fmstruct%ref_count = 1
313 IF (
PRESENT(descriptor))
THEN
314 fmstruct%descriptor = descriptor
316 fmstruct%descriptor = 0
317#if defined(__parallel)
319 CALL descinit(fmstruct%descriptor, fmstruct%nrow_global, &
320 fmstruct%ncol_global, fmstruct%nrow_block, &
321 fmstruct%ncol_block, fmstruct%first_p_pos(1), &
322 fmstruct%first_p_pos(2), fmstruct%context, &
323 fmstruct%local_leading_dimension, stat)
436 descriptor, ncol_block, nrow_block, nrow_global, &
437 ncol_global, first_p_pos, row_indices, &
438 col_indices, nrow_local, ncol_local, nrow_locals, ncol_locals, &
439 local_leading_dimension)
443 INTEGER,
DIMENSION(9),
INTENT(OUT),
OPTIONAL :: descriptor
444 INTEGER,
INTENT(out),
OPTIONAL :: ncol_block, nrow_block, nrow_global, &
446 INTEGER,
DIMENSION(2),
INTENT(out),
OPTIONAL :: first_p_pos
447 INTEGER,
DIMENSION(:),
OPTIONAL,
POINTER :: row_indices, col_indices
448 INTEGER,
INTENT(out),
OPTIONAL :: nrow_local, ncol_local
449 INTEGER,
DIMENSION(:),
OPTIONAL,
POINTER :: nrow_locals, ncol_locals
450 INTEGER,
INTENT(out),
OPTIONAL :: local_leading_dimension
452 IF (
PRESENT(para_env)) para_env => fmstruct%para_env
453 IF (
PRESENT(context)) context => fmstruct%context
454 IF (
PRESENT(descriptor)) descriptor = fmstruct%descriptor
455 IF (
PRESENT(ncol_block)) ncol_block = fmstruct%ncol_block
456 IF (
PRESENT(nrow_block)) nrow_block = fmstruct%nrow_block
457 IF (
PRESENT(nrow_global)) nrow_global = fmstruct%nrow_global
458 IF (
PRESENT(ncol_global)) ncol_global = fmstruct%ncol_global
459 IF (
PRESENT(first_p_pos)) first_p_pos = fmstruct%first_p_pos
460 IF (
PRESENT(nrow_locals)) nrow_locals => fmstruct%nrow_locals
461 IF (
PRESENT(ncol_locals)) ncol_locals => fmstruct%ncol_locals
462 IF (
PRESENT(local_leading_dimension)) local_leading_dimension = &
463 fmstruct%local_leading_dimension
465 IF (
PRESENT(nrow_local)) nrow_local = fmstruct%nrow_locals(fmstruct%context%mepos(1))
466 IF (
PRESENT(ncol_local)) ncol_local = fmstruct%ncol_locals(fmstruct%context%mepos(2))
468 IF (
PRESENT(row_indices)) row_indices => fmstruct%row_indices
469 IF (
PRESENT(col_indices)) col_indices => fmstruct%col_indices
526 LOGICAL,
INTENT(in) :: col, row
528 INTEGER :: n_doubled_items_in_partially_filled_block, ncol_block, ncol_global, newdim_col, &
529 newdim_row, nfilled_blocks, nfilled_blocks_remain, nprocs_col, nprocs_row, nrow_block, &
534 ncol_global=ncol_global, nrow_block=nrow_block, &
535 ncol_block=ncol_block)
536 newdim_row = nrow_global
537 newdim_col = ncol_global
538 nprocs_row = context%num_pe(1)
539 nprocs_col = context%num_pe(2)
540 para_env => struct%para_env
543 IF (ncol_global == 0)
THEN
553 n_doubled_items_in_partially_filled_block = 2*mod(ncol_global, ncol_block)
554 nfilled_blocks = ncol_global/ncol_block
555 nfilled_blocks_remain = mod(nfilled_blocks, nprocs_col)
556 newdim_col = 2*(nfilled_blocks/nprocs_col)
557 IF (n_doubled_items_in_partially_filled_block > ncol_block)
THEN
564 newdim_col = newdim_col + 1
567 n_doubled_items_in_partially_filled_block = n_doubled_items_in_partially_filled_block - ncol_block
568 ELSE IF (nfilled_blocks_remain > 0)
THEN
573 newdim_col = newdim_col + 1
574 n_doubled_items_in_partially_filled_block = 0
577 newdim_col = (newdim_col*nprocs_col + nfilled_blocks_remain)*ncol_block + n_doubled_items_in_partially_filled_block
582 IF (nrow_global == 0)
THEN
585 n_doubled_items_in_partially_filled_block = 2*mod(nrow_global, nrow_block)
586 nfilled_blocks = nrow_global/nrow_block
587 nfilled_blocks_remain = mod(nfilled_blocks, nprocs_row)
588 newdim_row = 2*(nfilled_blocks/nprocs_row)
589 IF (n_doubled_items_in_partially_filled_block > nrow_block)
THEN
590 newdim_row = newdim_row + 1
591 n_doubled_items_in_partially_filled_block = n_doubled_items_in_partially_filled_block - nrow_block
592 ELSE IF (nfilled_blocks_remain > 0)
THEN
593 newdim_row = newdim_row + 1
594 n_doubled_items_in_partially_filled_block = 0
597 newdim_row = (newdim_row*nprocs_row + nfilled_blocks_remain)*nrow_block + n_doubled_items_in_partially_filled_block
605 nrow_global=newdim_row, &
606 ncol_global=newdim_col, &
607 ncol_block=ncol_block, &
608 nrow_block=nrow_block, &
609 square_blocks=.false.)