Line data Source code
1 : !!****m* ABINIT/m_mpiotk
2 : !! NAME
3 : !! m_mpiotk
4 : !!
5 : !! FUNCTION
6 : !! This module provides helper functions for MPI-IO operations.
7 : !!
8 : !! COPYRIGHT
9 : !! Copyright (C) 2009-2026 ABINIT group (MG)
10 : !! This file is distributed under the terms of the
11 : !! GNU General Public License, see ~abinit/COPYING
12 : !! or http://www.gnu.org/copyleft/gpl.txt .
13 : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt.
14 : !!
15 : !! SOURCE
16 :
17 : #if defined HAVE_CONFIG_H
18 : #include "config.h"
19 : #endif
20 :
21 : #include "abi_common.h"
22 :
23 : MODULE m_mpiotk
24 :
25 : use defs_basis
26 : use m_abicore
27 : use m_errors
28 : use m_xmpi
29 : USE_MPI
30 :
31 : use iso_c_binding
32 :
33 : implicit none
34 :
35 : #if defined HAVE_MPI1 && defined HAVE_MPI_IO
36 : include 'mpif.h'
37 : #endif
38 :
39 : private
40 :
41 : !public procedures.
42 : #ifdef HAVE_MPI_IO
43 : public :: mpiotk_read_fsuba_dp2D ! (individual|collective) read of a 2D sub-matrix
44 : public :: mpiotk_write_fsuba_dp2D ! (individual|collective) write of a 2D sub-matrix
45 :
46 : public :: mpiotk_read_fsuba_dpc3D ! (individual|collective) read of a 3D sub-matrix
47 : !public :: mpiotk_write_fsuba_dpc3D ! (individual|collective) write of a 3D sub-matrix
48 :
49 : public :: mpiotk_read_fsuba_dpc4D ! (individual|collective) read of a 4D sub-matrix
50 : !public :: mpiotk_write_fsuba_dpc4D ! (individual|collective) write of a 4D sub-matrix
51 : #else
52 : public :: no_mpiotk
53 : #endif
54 : !!***
55 :
56 : CONTAINS
57 : !!***
58 :
59 : #ifndef HAVE_MPI_IO
60 :
61 : !----------------------------------------------------------------------
62 :
63 : !!****f* m_mpiotk/no_mpiotk
64 : !! NAME
65 : !! no_mpiotk
66 : !!
67 : !! FUNCTION
68 : !! Empty placeholder.
69 : !!
70 : !! SOURCE
71 :
72 : subroutine no_mpiotk()
73 :
74 : ! *************************************************************************
75 :
76 : end subroutine no_mpiotk
77 : !!***
78 :
79 : #else
80 :
81 : !!****f* m_mpiotk/setup_fsuba_dp2D
82 : !! NAME
83 : !! setup_fsuba_dp2D
84 : !!
85 : !! FUNCTION
86 : !! Setup tables used in (read|write) a 2D array stored in a Fortran file
87 : !!
88 : !! NOTES
89 : !! The value of ierr should always be checked by the caller
90 : !!
91 : !! INPUTS
92 : !! sizes(2)
93 : !! subsizes(2)
94 : !! starts(2)
95 : !! chunk_bsize =
96 : !! comm = MPI communicator
97 : !!
98 : !! OUTPUTS
99 : !! my_basead(:)
100 : !! my_subsizes(:,:)
101 : !! my_starts(:,:)
102 : !! ierr=status error. A non zero value indicates that chunk_bsize is smaller that the fortran record
103 : !! and therefore bufsz has not been read.
104 : !!
105 : !! SOURCE
106 :
107 30 : subroutine setup_fsuba_dp2D(sizes,subsizes,starts,chunk_bsize,&
108 : my_basead,my_subsizes,my_starts,my_ncalls,ncalls,comm,ierr)
109 :
110 : !Arguments ------------------------------------
111 : !scalars
112 : integer,intent(in) :: comm
113 : integer,intent(out) :: ncalls,my_ncalls,ierr
114 : integer(XMPI_OFFSET_KIND),intent(in) :: chunk_bsize
115 : !arrays
116 : integer,intent(in) :: sizes(2),subsizes(2),starts(2)
117 : integer,allocatable,intent(out) :: my_basead(:),my_subsizes(:,:),my_starts(:,:)
118 :
119 : !Local variables ------------------------------
120 : !scalars
121 : integer :: mpierr,ny2read,ny_chunk,icall,yrest
122 : integer :: size_x,subs_x,start_x,start_y,stop_y
123 : !character(len=500) :: msg
124 :
125 : !************************************************************************
126 :
127 30 : size_x = sizes(1)
128 30 : subs_x = subsizes(1)
129 30 : start_x = starts(1)
130 30 : start_y = starts(2)
131 30 : stop_y = start_y + subsizes(2)-1 ! last column to read
132 : !
133 : ! Read rows in blocks of size ny_chunk:
134 : ! MPI-IO crashes if we try to read data > 2Gb in a single call.
135 30 : ny2read = subsizes(2)
136 30 : ny_chunk = ny2read
137 30 : if ((two*subs_x*ny2read*xmpi_bsize_dp) > chunk_bsize) then
138 0 : ny_chunk = chunk_bsize / (2*subs_x*xmpi_bsize_dp)
139 : !if (ny_chunk == 0) ny_chunk = 50
140 : end if
141 :
142 30 : call xmpi_min(ny_chunk,ierr,comm,mpierr)
143 30 : if (ierr == 0) then
144 0 : ierr = 1
145 0 : RETURN
146 : end if
147 30 : ierr = 0
148 : !
149 : ! my_ncalls : number of read needed to fill my buffer.
150 : ! ncalls : max number of read in comm (needed for collective operations).
151 30 : my_ncalls = ny2read / ny_chunk
152 30 : yrest = MOD(ny2read, ny_chunk)
153 30 : if (yrest /= 0) my_ncalls = my_ncalls + 1
154 :
155 30 : call xmpi_max(my_ncalls,ncalls,comm,mpierr)
156 : !
157 : ! Compute arrays used to define the file view.
158 90 : ABI_MALLOC(my_subsizes,(2,ncalls))
159 60 : ABI_MALLOC(my_starts,(2,ncalls))
160 90 : ABI_MALLOC(my_basead,(ncalls))
161 :
162 60 : do icall=1,my_ncalls
163 :
164 60 : if (icall*ny_chunk <= ny2read) then
165 90 : my_subsizes(:,icall) = (/subs_x, ny_chunk/)
166 90 : my_starts(:,icall) = (/start_x, (icall-1) * ny_chunk + start_y/)
167 30 : my_basead(icall) = 1 + 2*(icall-1)*ny_chunk*subs_x ! 2 accounts for real and imag part.
168 : else
169 : ! Two cases:
170 : ! 1) ny2read > ny_chunk and not divisible by ny2read
171 : ! 2) ny2read < ny_chunk
172 0 : my_subsizes(:,icall) = (/subs_x, yrest/)
173 0 : if (ny2read >= ny_chunk) then
174 0 : my_starts(:,icall) = (/start_x, stop_y-yrest+1/)
175 0 : my_basead(icall) = 1 + 2 * (ny2read-yrest) * subs_x ! 2 accounts for real and imag part.
176 : else
177 0 : my_starts(:,icall) = starts
178 0 : my_basead(icall) = 1
179 : end if
180 : end if
181 : end do
182 : !write(std_out,*)" >>>> my_ncalls, ncalls, ny2read, ny_chunk ",my_ncalls,ncalls,ny2read,ny_chunk
183 :
184 60 : end subroutine setup_fsuba_dp2D
185 : !!***
186 :
187 : !----------------------------------------------------------------------
188 :
189 : !!****f* m_mpiotk/mpiotk_read_fsuba_dp2D
190 : !! NAME
191 : !! mpiotk_read_fsuba_dp2D
192 : !!
193 : !! FUNCTION
194 : !! Read a block of contiguous data stored in a 2D matrix.
195 : !! Data is placed within Fortran records. Target: complex data stored in a real array.
196 : !!
197 : !! NOTES
198 : !! The value of ierr should always be checked by the caller
199 : !!
200 : !! INPUTS
201 : !! fh = MPI-IO file handler.
202 : !! offset =
203 : !! sizes(2)
204 : !! subsizes(2)
205 : !! starts(2)
206 : !! bufsz = dimension of buffer (takes into accout both real and imaginary part)
207 : !! chunk_bsize =
208 : !! sc_mode= MPI-IO option
209 : !! xmpio_single ==> for reading by current proc.
210 : !! xmpio_collective ==> for collective reading.
211 : !! comm = MPI communicator
212 : !!
213 : !! OUTPUTS
214 : !! buffer(bufsz)
215 : !! ierr=status error. A non zero value indicates that chunk_bsize is smaller that the fortran record
216 : !! and therefore bufsz has not been read.
217 : !!
218 : !! SOURCE
219 :
220 0 : subroutine mpiotk_read_fsuba_dp2D(fh,offset,sizes,subsizes,starts,bufsz,buffer,chunk_bsize,sc_mode,comm,ierr)
221 :
222 : !Arguments ------------------------------------
223 : !scalars
224 : integer,intent(in) :: fh,comm,bufsz,sc_mode
225 : integer,intent(out) :: ierr
226 : integer(XMPI_OFFSET_KIND),intent(in) :: offset,chunk_bsize
227 : !arrays
228 : integer,intent(in) :: sizes(2),subsizes(2),starts(2)
229 : real(dp),intent(out),target :: buffer(bufsz)
230 :
231 : !Local variables ------------------------------
232 : !scalars
233 : integer :: mpierr,ptr,ncount,myfh
234 : integer :: fsub_type,my_ncalls,icall,ncalls,subs_x
235 : integer(XMPI_OFFSET_KIND) :: my_offset,my_offpad
236 : !character(len=500) :: msg
237 : type(c_ptr) :: cptr
238 : !arrays
239 : integer :: call_subsizes(2),call_starts(2)
240 0 : integer,allocatable :: my_basead(:),my_subsizes(:,:),my_starts(:,:)
241 0 : real(dp),allocatable :: dummy_buf(:,:)
242 0 : real(dp),pointer :: buf_ptr(:)
243 :
244 : !************************************************************************
245 :
246 : ! Workaround for XLF
247 0 : myfh = fh
248 :
249 0 : if (bufsz < 2 * PRODUCT(subsizes) ) then
250 0 : ABI_ERROR("bufsz is too small")
251 : end if
252 :
253 0 : if (sc_mode==xmpio_single) then
254 : ! This makes the automatic tests fail (cut3d)
255 : !ABI_WARNING("comm != xmpi_comm_self")
256 0 : else if (sc_mode==xmpio_collective) then
257 : continue
258 : else
259 0 : ABI_ERROR("Wrong sc_mode")
260 : end if
261 :
262 0 : subs_x = subsizes(1)
263 :
264 0 : call setup_fsuba_dp2D(sizes,subsizes,starts,chunk_bsize,my_basead,my_subsizes,my_starts,my_ncalls,ncalls,comm,ierr)
265 0 : if (ierr/=0) RETURN
266 :
267 0 : do icall=1,ncalls
268 :
269 0 : if (icall <= my_ncalls) then
270 0 : call_subsizes = my_subsizes(:,icall)
271 0 : call_starts = my_starts(:,icall)
272 0 : ptr = my_basead(icall)
273 : else
274 : ! Fake values needed to call read_all collectively.
275 0 : call_subsizes = (/subs_x, 1/)
276 0 : call_starts = starts
277 : end if
278 0 : ncount = PRODUCT(call_subsizes)
279 : !write(std_out,*)" icall,ptr, ncount, ",icall,ptr,ncount
280 : !write(std_out,*)" call_starts",call_starts
281 : !write(std_out,*)" call_subsizes",call_subsizes
282 :
283 : ! Create subarry file view.
284 0 : call xmpio_create_fsubarray_2D(sizes,call_subsizes,call_starts,MPI_DOUBLE_COMPLEX,fsub_type,my_offpad,mpierr)
285 0 : ABI_CHECK_MPI(mpierr,"fsubarray_2D")
286 :
287 : ! Update the offset.
288 0 : my_offset = offset + my_offpad
289 :
290 0 : call MPI_FILE_SET_VIEW(myfh, my_offset, MPI_BYTE, fsub_type, 'native', MPI_INFO_NULL, mpierr)
291 0 : ABI_CHECK_MPI(mpierr,"SET_VIEW")
292 :
293 0 : call MPI_TYPE_FREE(fsub_type, mpierr)
294 0 : ABI_CHECK_MPI(mpierr,"MPI_TYPE_FREE")
295 :
296 0 : if (sc_mode==xmpio_collective) then
297 : ! Collective read
298 0 : if (icall <= my_ncalls) then
299 0 : cptr=c_loc(buffer(ptr)) ; call c_f_pointer(cptr,buf_ptr,[ncount])
300 0 : call MPI_FILE_READ_ALL(myfh, buf_ptr, ncount, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpierr)
301 : else
302 0 : ABI_MALLOC(dummy_buf,(2,subs_x))
303 0 : call MPI_FILE_READ_ALL(myfh, dummy_buf, ncount, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpierr)
304 0 : ABI_FREE(dummy_buf)
305 : end if
306 0 : ABI_CHECK_MPI(mpierr,"FILE_READ_ALL")
307 :
308 : else
309 : ! Individual read.
310 0 : cptr=c_loc(buffer(ptr)) ; call c_f_pointer(cptr,buf_ptr,[ncount])
311 0 : call MPI_FILE_READ(myfh, buf_ptr, ncount, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpierr)
312 0 : ABI_CHECK_MPI(mpierr,"FILE_READ")
313 : end if
314 :
315 : end do
316 :
317 0 : ABI_FREE(my_subsizes)
318 0 : ABI_FREE(my_starts)
319 0 : ABI_FREE(my_basead)
320 :
321 0 : end subroutine mpiotk_read_fsuba_dp2D
322 : !!***
323 :
324 : !----------------------------------------------------------------------
325 :
326 : !!****f* m_mpiotk/mpiotk_write_fsuba_dp2D
327 : !! NAME
328 : !! mpiotk_write_fsuba_dp2D
329 : !!
330 : !! FUNCTION
331 : !! Write a block of contiguous data stored in a 2D matrix.
332 : !! Data is placed within Fortran records. Target: complex data stored in a real array.
333 : !!
334 : !! NOTES
335 : !! The value of ierr should always be checked by the caller
336 : !!
337 : !! INPUTS
338 : !! fh = MPI-IO file handler.
339 : !! offset =
340 : !! sizes(2)
341 : !! subsizes(2)
342 : !! starts(2)
343 : !! bufsz = dimension of buffer (takes into accout both real and imaginary part)
344 : !! buffer(bufsz)
345 : !! chunk_bsize =
346 : !! sc_mode= MPI-IO option
347 : !! xmpio_single ==> for reading by current proc.
348 : !! xmpio_collective ==> for collective reading.
349 : !! comm = MPI communicator
350 : !!
351 : !! OUTPUTS
352 : !! ierr=status error. A non zero value indicates that chunk_bsize is smaller that the fortran record
353 : !! and therefore bufsz has not been written.
354 : !!
355 : !! SOURCE
356 :
357 30 : subroutine mpiotk_write_fsuba_dp2D(fh,offset,sizes,subsizes,starts,bufsz,buffer,chunk_bsize,sc_mode,comm,ierr)
358 :
359 : !Arguments ------------------------------------
360 : !scalars
361 : integer,intent(in) :: fh,comm,bufsz,sc_mode
362 : integer,intent(out) :: ierr
363 : integer(XMPI_OFFSET_KIND),intent(in) :: offset,chunk_bsize
364 : !arrays
365 : integer,intent(in) :: sizes(2),subsizes(2),starts(2)
366 : real(dp),intent(in),target :: buffer(bufsz)
367 :
368 : !Local variables ------------------------------
369 : !scalars
370 : integer :: mpierr,ptr,ncount,myfh
371 : integer :: fsub_type,my_ncalls,icall,ncalls,subs_x
372 : integer(XMPI_OFFSET_KIND) :: my_offset,my_offpad
373 : type(c_ptr) :: cptr
374 : !character(len=500) :: msg
375 : !arrays
376 : integer :: call_subsizes(2),call_starts(2)
377 30 : integer,allocatable :: my_basead(:),my_subsizes(:,:),my_starts(:,:)
378 30 : real(dp),pointer :: buf_ptr(:)
379 :
380 : !************************************************************************
381 :
382 : DBG_ENTER("COLL")
383 :
384 : ! Workaround for XLF
385 30 : myfh = fh
386 :
387 90 : if (bufsz < 2 * PRODUCT(subsizes) ) then
388 0 : ABI_ERROR("bufsz is too small")
389 : end if
390 :
391 30 : if (sc_mode==xmpio_single) then
392 30 : call setup_fsuba_dp2D(sizes,subsizes,starts,chunk_bsize,my_basead,my_subsizes,my_starts,my_ncalls,ncalls,xmpi_comm_self,ierr)
393 0 : else if (sc_mode==xmpio_collective) then
394 0 : call setup_fsuba_dp2D(sizes,subsizes,starts,chunk_bsize,my_basead,my_subsizes,my_starts,my_ncalls,ncalls,comm,ierr)
395 : else
396 0 : ABI_ERROR("Wrong sc_mode")
397 : end if
398 30 : if (ierr/=0) RETURN
399 :
400 30 : subs_x = subsizes(1)
401 60 : do icall=1,ncalls
402 :
403 30 : if (icall <= my_ncalls) then
404 90 : call_subsizes = my_subsizes(:,icall)
405 90 : call_starts = my_starts(:,icall)
406 30 : ptr = my_basead(icall)
407 : else
408 : ! Fake values needed to call write_all collectively.
409 0 : call_subsizes = (/subs_x, 1/)
410 0 : call_starts = starts
411 : end if
412 90 : ncount = PRODUCT(call_subsizes)
413 : !write(std_out,*)" icall,ptr, ncount, ",icall,ptr,ncount
414 : !write(std_out,*)" call_starts",call_starts
415 : !write(std_out,*)" call_subsizes",call_subsizes
416 :
417 : ! Create subarry file view.
418 30 : call xmpio_create_fsubarray_2D(sizes,call_subsizes,call_starts,MPI_DOUBLE_COMPLEX,fsub_type,my_offpad,mpierr)
419 30 : ABI_CHECK_MPI(mpierr,"fsubarray_2D")
420 :
421 : ! Update the offset.
422 30 : my_offset = offset + my_offpad
423 :
424 30 : call MPI_FILE_SET_VIEW(myfh, my_offset, MPI_BYTE, fsub_type, 'native', MPI_INFO_NULL, mpierr)
425 30 : ABI_CHECK_MPI(mpierr,"SET_VIEW")
426 :
427 30 : call MPI_TYPE_FREE(fsub_type, mpierr)
428 30 : ABI_CHECK_MPI(mpierr,"MPI_TYPE_FREE")
429 :
430 60 : if (sc_mode==xmpio_collective) then
431 : ! Collective write
432 0 : if (icall <= my_ncalls) then
433 0 : cptr=c_loc(buffer(ptr)) ; call c_f_pointer(cptr,buf_ptr,[ncount])
434 0 : call MPI_FILE_WRITE_ALL(myfh, buf_ptr, ncount, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpierr)
435 : else
436 : ! Re-write my first chunk of data.
437 0 : cptr=c_loc(buffer(1)) ; call c_f_pointer(cptr,buf_ptr,[ncount])
438 0 : call MPI_FILE_WRITE_ALL(myfh, buf_ptr, ncount, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpierr)
439 : end if
440 0 : ABI_CHECK_MPI(mpierr,"FILE_WRITE_ALL")
441 :
442 : else
443 : ! Individual write.
444 60 : cptr=c_loc(buffer(ptr)) ; call c_f_pointer(cptr,buf_ptr,[ncount])
445 30 : call MPI_FILE_WRITE(myfh, buf_ptr, ncount, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpierr)
446 30 : ABI_CHECK_MPI(mpierr,"FILE_WRITE")
447 : end if
448 :
449 : end do
450 :
451 30 : ABI_FREE(my_subsizes)
452 30 : ABI_FREE(my_starts)
453 30 : ABI_FREE(my_basead)
454 :
455 : DBG_EXIT("COLL")
456 :
457 30 : end subroutine mpiotk_write_fsuba_dp2D
458 : !!***
459 :
460 : !----------------------------------------------------------------------
461 :
462 : !!****f* m_mpiotk/mpiotk_read_fsuba_dpc3D
463 : !! NAME
464 : !! mpiotk_read_fsuba_dpc3D
465 : !!
466 : !! FUNCTION
467 : !! Read of a block of contiguous data stored in a 3D matrix.
468 : !! Data is placed within Fortran records. Target: complex data stored in a complex array.
469 : !!
470 : !! NOTES
471 : !! The value of ierr should always be checked by the caller
472 : !!
473 : !! INPUTS
474 : !! fh = MPI-IO file handler.
475 : !! offset =
476 : !! sizes(3)
477 : !! subsizes(3)
478 : !! starts(3)
479 : !! bufsz = dimension of cbuffer
480 : !! chunk_bsize =
481 : !! comm = MPI communicator
482 : !! sc_mode= MPI-IO option
483 : !! xmpio_single ==> for reading by current proc.
484 : !! xmpio_collective ==> for collective reading.
485 : !!
486 : !! OUTPUTS
487 : !! cbuffer(bufsz)
488 : !! ierr=status error. A non zero value indicates that chunk_bsize is smaller that the fortran record
489 : !! and therefore bufsz has not been read.
490 : !!
491 : !! SOURCE
492 :
493 0 : subroutine mpiotk_read_fsuba_dpc3D(fh,offset,sizes,subsizes,starts,bufsz,cbuffer,chunk_bsize,sc_mode,comm,ierr)
494 :
495 : !Arguments ------------------------------------
496 : !scalars
497 : integer,intent(in) :: fh,comm,bufsz,sc_mode
498 : integer,intent(out) :: ierr
499 : integer(XMPI_OFFSET_KIND),intent(in) :: offset,chunk_bsize
500 : !arrays
501 : integer,intent(in) :: sizes(3),subsizes(3),starts(3)
502 : complex(dp),intent(out),target :: cbuffer(bufsz)
503 :
504 : !Local variables-------------------------------
505 : !scalars
506 : integer :: mpierr,nz2read,nz_chunk,ptr,ncount,myfh
507 : integer :: fsub_type,my_ncalls,icall,zrest,ncalls
508 : integer :: size_x,size_y,subs_x,subs_y,subs_xy,start_x,start_y,start_z,stop_z
509 : integer(XMPI_OFFSET_KIND) :: my_offset,my_offpad
510 : !character(len=500) :: msg
511 : type(c_ptr) :: cptr
512 : !arrays
513 : integer :: call_subsizes(3),call_starts(3)
514 0 : integer,allocatable :: my_basead(:),my_subsizes(:,:),my_starts(:,:)
515 0 : complex(dp),allocatable :: dummy_cbuf(:)
516 0 : complex(dp),pointer :: buf_ptr(:)
517 : !************************************************************************
518 :
519 : ! Workaround for XLF
520 0 : myfh = fh
521 :
522 0 : if (bufsz < PRODUCT(subsizes) ) then
523 0 : ABI_ERROR("bufsz is too small")
524 : end if
525 :
526 0 : if (sc_mode==xmpio_single) then
527 0 : ABI_CHECK(comm==xmpi_comm_self,"comm != xmpi_comm_self")
528 0 : else if (sc_mode==xmpio_collective) then
529 : continue
530 : else
531 0 : ABI_ERROR("Wrong sc_mode")
532 : end if
533 :
534 0 : size_x = sizes(1)
535 0 : size_y = sizes(2)
536 0 : subs_x = subsizes(1)
537 0 : subs_y = subsizes(2)
538 0 : subs_xy = subs_x * subs_y
539 0 : start_x = starts(1)
540 0 : start_y = starts(2)
541 0 : start_z = starts(3)
542 0 : stop_z = start_z + subsizes(3)-1 ! last column to read
543 :
544 : ! Read rows in blocks of size nz_chunk:
545 : ! MPI-IO crashes if we try to read data > 2Gb in a single call.
546 0 : nz2read = subsizes(3)
547 0 : nz_chunk = nz2read
548 0 : if ( (one*subs_xy*nz2read*xmpi_bsize_dpc) > chunk_bsize) then
549 0 : nz_chunk = chunk_bsize / (subs_xy*xmpi_bsize_dpc)
550 : !if (nz_chunk == 0) nz_chunk = 50
551 : end if
552 :
553 0 : call xmpi_min(nz_chunk,ierr,comm,mpierr)
554 0 : if (ierr == 0) then
555 0 : ierr = 1
556 : RETURN
557 : end if
558 0 : ierr = 0
559 :
560 : ! my_ncalls : number of read needed to fill my cbuffer.
561 : ! ncalls : max number of read in comm (needed for collective operations).
562 0 : my_ncalls = nz2read / nz_chunk
563 0 : zrest = MOD(nz2read, nz_chunk)
564 0 : if (zrest /= 0) my_ncalls = my_ncalls + 1
565 :
566 0 : call xmpi_max(my_ncalls,ncalls,comm,mpierr)
567 :
568 : ! Compute arrays used to define the file view.
569 0 : ABI_MALLOC(my_subsizes,(3,ncalls))
570 0 : ABI_MALLOC(my_starts,(3,ncalls))
571 0 : ABI_MALLOC(my_basead,(ncalls))
572 :
573 0 : do icall=1,my_ncalls
574 0 : if (icall*nz_chunk <= nz2read) then
575 0 : my_subsizes(:,icall) = (/subs_x, subs_y, nz_chunk/)
576 0 : my_starts(:,icall) = (/start_x, start_y, (icall-1) * nz_chunk + start_z/)
577 0 : my_basead(icall) = 1 + (icall-1)*subs_xy*nz_chunk
578 : else
579 : ! Two cases:
580 : ! 1) nz2read > nz_chunk and not divisible by nz2read
581 : ! 2) nz2read < nz_chunk
582 0 : my_subsizes(:,icall) = (/subs_x, subs_y, zrest/)
583 0 : if (nz2read >= nz_chunk) then
584 0 : my_starts(:,icall) = (/start_x, start_y, stop_z-zrest+1/)
585 0 : my_basead(icall) = 1 + (nz2read-zrest) * subs_xy
586 : else
587 0 : my_starts(:,icall) = starts
588 0 : my_basead(icall) = 1
589 : end if
590 : end if
591 : end do
592 : !write(std_out,*)" >>>> my_ncalls, ncalls, nz2read, nz_chunk ",my_ncalls,ncalls,nz2read,nz_chunk
593 :
594 0 : do icall=1,ncalls
595 :
596 0 : if (icall <= my_ncalls) then
597 0 : call_subsizes = my_subsizes(:,icall)
598 0 : call_starts = my_starts(:,icall)
599 0 : ptr = my_basead(icall)
600 : else
601 : ! Fake values needed to call read_all collectively.
602 0 : call_subsizes = (/subs_x, 1, 1/)
603 0 : call_starts = starts
604 : end if
605 0 : ncount = PRODUCT(call_subsizes)
606 : !write(std_out,*)" icall,ptr, ncount, ",icall,ptr,ncount
607 : !write(std_out,*)" call_starts",call_starts
608 : !write(std_out,*)" call_subsizes",call_subsizes
609 :
610 : ! Create subarry file view.
611 : call xmpio_create_fsubarray_3D(sizes,call_subsizes,call_starts,MPI_DOUBLE_COMPLEX,&
612 0 : & fsub_type,my_offpad,mpierr)
613 0 : ABI_CHECK_MPI(mpierr,"fsubarray_3D")
614 :
615 : ! Update the offset.
616 0 : my_offset = offset + my_offpad
617 :
618 0 : call MPI_FILE_SET_VIEW(myfh, my_offset, MPI_BYTE, fsub_type, 'native', MPI_INFO_NULL, mpierr)
619 0 : ABI_CHECK_MPI(mpierr,"SET_VIEW")
620 :
621 0 : call MPI_TYPE_FREE(fsub_type, mpierr)
622 0 : ABI_CHECK_MPI(mpierr,"MPI_TYPE_FREE")
623 :
624 0 : if (sc_mode==xmpio_collective) then
625 : ! Collective read
626 0 : if (icall <= my_ncalls) then
627 0 : cptr=c_loc(cbuffer(ptr)) ; call c_f_pointer(cptr,buf_ptr,[ncount])
628 0 : call MPI_FILE_READ_ALL(myfh, buf_ptr, ncount, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpierr)
629 : else
630 0 : ABI_MALLOC(dummy_cbuf,(subs_x))
631 0 : call MPI_FILE_READ_ALL(myfh, dummy_cbuf, ncount, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpierr)
632 0 : ABI_FREE(dummy_cbuf)
633 : end if
634 0 : ABI_CHECK_MPI(mpierr,"FILE_READ_ALL")
635 :
636 : else
637 : ! Individual read.
638 0 : cptr=c_loc(cbuffer(ptr)) ; call c_f_pointer(cptr,buf_ptr,[ncount])
639 0 : call MPI_FILE_READ(myfh, buf_ptr, ncount, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpierr)
640 0 : ABI_CHECK_MPI(mpierr,"FILE_READ")
641 : end if
642 :
643 : end do
644 :
645 0 : ABI_FREE(my_subsizes)
646 0 : ABI_FREE(my_starts)
647 0 : ABI_FREE(my_basead)
648 :
649 0 : end subroutine mpiotk_read_fsuba_dpc3D
650 : !!***
651 :
652 : !----------------------------------------------------------------------
653 :
654 : !!****f* m_mpiotk/mpiotk_read_fsuba_dpc4D
655 : !! NAME
656 : !! mpiotk_read_fsuba_dpc4D
657 : !!
658 : !! FUNCTION
659 : !! Reading a block of contiguous data stored in a 4D matrix.
660 : !! Data is placed within Fortran records. Target: complex data stored in a complex array.
661 : !!
662 : !! NOTES
663 : !! The value of ierr should always be checked by the caller
664 : !!
665 : !! INPUTS
666 : !! fh = MPI-IO file handler.
667 : !! offset =
668 : !! sizes(4)
669 : !! subsizes(4)
670 : !! starts(4)
671 : !! bufsz = dimension of cbuffer
672 : !! chunk_bsize =
673 : !! comm = MPI communicator
674 : !! sc_mode= MPI-IO option
675 : !! xmpio_single ==> for reading by current proc.
676 : !! xmpio_collective ==> for collective reading.
677 : !!
678 : !! OUTPUTS
679 : !! cbuffer(bufsz)
680 : !! ierr=status error. A non zero value indicates that chunk_bsize is smaller that the fortran record
681 : !! and therefore bufsz has not been read.
682 : !!
683 : !! SOURCE
684 :
685 0 : subroutine mpiotk_read_fsuba_dpc4D(fh,offset,sizes,subsizes,starts,bufsz,cbuffer,chunk_bsize,sc_mode,comm,ierr)
686 :
687 : !Arguments ------------------------------------
688 : !scalars
689 : integer,intent(in) :: fh,comm,bufsz,sc_mode
690 : integer,intent(out) :: ierr
691 : integer(XMPI_OFFSET_KIND),intent(in) :: offset,chunk_bsize
692 : !arrays
693 : integer,intent(in) :: sizes(4),subsizes(4),starts(4)
694 : complex(dp),intent(out),target :: cbuffer(bufsz)
695 :
696 : !Local variables-------------------------------
697 : !scalars
698 : integer :: mpierr,na2read,na_chunk,ptr,ncount,myfh
699 : integer :: fsub_type,my_ncalls,icall,arest,ncalls
700 : integer :: size_x,size_y,size_z,subs_x,subs_y,subs_z,subs_xyz,start_x,start_y,start_z,start_a,stop_a
701 : integer(XMPI_OFFSET_KIND) :: my_offset,my_offpad
702 : !character(len=500) :: msg
703 : type(c_ptr) :: cptr
704 : !arrays
705 : integer :: call_subsizes(4),call_starts(4)
706 0 : integer,allocatable :: my_basead(:),my_subsizes(:,:),my_starts(:,:)
707 0 : complex(dp),allocatable :: dummy_cbuf(:)
708 0 : complex(dp),pointer :: buf_ptr(:)
709 : !************************************************************************
710 :
711 : ! Workaround for XLF
712 0 : myfh = fh
713 :
714 0 : if (bufsz < PRODUCT(subsizes) ) then
715 0 : ABI_ERROR("bufsz is too small")
716 : end if
717 :
718 0 : if (sc_mode==xmpio_single) then
719 0 : ABI_CHECK(comm==xmpi_comm_self,"comm != xmpi_comm_self")
720 0 : else if (sc_mode==xmpio_collective) then
721 : continue
722 : else
723 0 : ABI_ERROR("Wrong sc_mode")
724 : end if
725 :
726 0 : size_x = sizes(1)
727 0 : size_y = sizes(2)
728 0 : size_z = sizes(3)
729 :
730 0 : subs_x = subsizes(1)
731 0 : subs_y = subsizes(2)
732 0 : subs_z = subsizes(3)
733 0 : subs_xyz = subs_x * subs_y * subs_z
734 :
735 0 : start_x = starts(1)
736 0 : start_y = starts(2)
737 0 : start_z = starts(3)
738 0 : start_a = starts(4)
739 0 : stop_a = start_a + subsizes(4)-1 ! last column to read
740 :
741 : ! Read rows in blocks of size na_chunk:
742 : ! MPI-IO crashes if we try to read data > 2Gb in a single call.
743 0 : na2read = subsizes(4)
744 0 : na_chunk = na2read
745 0 : if ( (one*subs_xyz*na2read*xmpi_bsize_dpc) > chunk_bsize) then
746 0 : na_chunk = chunk_bsize / (subs_xyz*xmpi_bsize_dpc)
747 : end if
748 :
749 0 : call xmpi_min(na_chunk,ierr,comm,mpierr)
750 0 : if (ierr == 0) then
751 0 : ierr = 1
752 : RETURN
753 : end if
754 0 : ierr = 0
755 :
756 : ! my_ncalls : number of read needed to fill my cbuffer.
757 : ! ncalls : max number of read in comm (needed for collective operations).
758 0 : my_ncalls = na2read / na_chunk
759 0 : arest = MOD(na2read, na_chunk)
760 0 : if (arest /= 0) my_ncalls = my_ncalls + 1
761 :
762 0 : call xmpi_max(my_ncalls,ncalls,comm,mpierr)
763 :
764 : ! Compute arrays used to define the file view.
765 0 : ABI_MALLOC(my_subsizes,(4,ncalls))
766 0 : ABI_MALLOC(my_starts,(4,ncalls))
767 0 : ABI_MALLOC(my_basead,(ncalls))
768 :
769 0 : do icall=1,my_ncalls
770 :
771 0 : if (icall*na_chunk <= na2read) then
772 0 : my_subsizes(:,icall) = (/subs_x, subs_y, subs_z, na_chunk/)
773 0 : my_starts(:,icall) = (/start_x, start_y, start_z, (icall-1) * na_chunk + start_a/)
774 0 : my_basead(icall) = 1 + (icall-1)*subs_xyz*na_chunk
775 : else
776 : ! Two cases:
777 : ! 1) na2read > na_chunk and not divisible by na2read
778 : ! 2) na2read < na_chunk
779 0 : my_subsizes(:,icall) = (/subs_x, subs_y, subs_z, arest/)
780 0 : if (na2read >= na_chunk) then
781 0 : my_starts(:,icall) = (/start_x, start_y, start_z, stop_a-arest+1/)
782 0 : my_basead(icall) = 1 + (na2read-arest) * subs_xyz
783 : else
784 0 : my_starts(:,icall) = starts
785 0 : my_basead(icall) = 1
786 : end if
787 : end if
788 : end do
789 : !write(std_out,*)" >>>> my_ncalls, ncalls, na2read, na_chunk ",my_ncalls,ncalls,na2read,na_chunk
790 :
791 0 : do icall=1,ncalls
792 :
793 0 : if (icall <= my_ncalls) then
794 0 : call_subsizes = my_subsizes(:,icall)
795 0 : call_starts = my_starts(:,icall)
796 0 : ptr = my_basead(icall)
797 : else
798 : ! Fake values needed to call read_all collectively.
799 0 : call_subsizes = (/subs_x, 1, 1, 1/)
800 0 : call_starts = starts
801 : end if
802 0 : ncount = PRODUCT(call_subsizes)
803 : !
804 : !write(std_out,*)" icall,ptr, ncount, ",icall,ptr,ncount
805 : !write(std_out,*)" call_starts",call_starts
806 : !write(std_out,*)" call_subsizes",call_subsizes
807 : !
808 : ! Create subarry file view.
809 : call xmpio_create_fsubarray_4D(sizes,call_subsizes,call_starts,MPI_DOUBLE_COMPLEX,&
810 0 : & fsub_type,my_offpad,mpierr)
811 0 : ABI_CHECK_MPI(mpierr,"fsubarray_4D")
812 :
813 : ! Update the offset.
814 0 : my_offset = offset + my_offpad
815 :
816 0 : call MPI_FILE_SET_VIEW(myfh, my_offset, MPI_BYTE, fsub_type, 'native', MPI_INFO_NULL, mpierr)
817 0 : ABI_CHECK_MPI(mpierr,"SET_VIEW")
818 :
819 0 : call MPI_TYPE_FREE(fsub_type, mpierr)
820 0 : ABI_CHECK_MPI(mpierr,"MPI_TYPE_FREE")
821 :
822 0 : if (sc_mode==xmpio_collective) then
823 : ! Collective read
824 0 : if (icall <= my_ncalls) then
825 0 : cptr=c_loc(cbuffer(ptr)) ; call c_f_pointer(cptr,buf_ptr,[ncount])
826 0 : call MPI_FILE_READ_ALL(myfh, cbuffer(ptr:), ncount, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpierr)
827 : else
828 0 : ABI_MALLOC(dummy_cbuf,(subs_x))
829 0 : call MPI_FILE_READ_ALL(myfh, dummy_cbuf, ncount, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpierr)
830 0 : ABI_FREE(dummy_cbuf)
831 : end if
832 0 : ABI_CHECK_MPI(mpierr,"FILE_READ_ALL")
833 : else
834 : ! Individual read.
835 0 : cptr=c_loc(cbuffer(ptr)) ; call c_f_pointer(cptr,buf_ptr,[ncount])
836 0 : call MPI_FILE_READ(myfh, buf_ptr, ncount, MPI_DOUBLE_COMPLEX, MPI_STATUS_IGNORE, mpierr)
837 0 : ABI_CHECK_MPI(mpierr,"FILE_READ")
838 : end if
839 :
840 : end do
841 :
842 0 : ABI_FREE(my_subsizes)
843 0 : ABI_FREE(my_starts)
844 0 : ABI_FREE(my_basead)
845 :
846 0 : end subroutine mpiotk_read_fsuba_dpc4D
847 : !!***
848 : #endif
849 :
850 : END MODULE m_mpiotk
851 : !!***
|