LCOV - code coverage report
Current view: top level - shared/common/src/27_toolbox_oop - m_mpiotk.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 20.1 % 274 55
Test Date: 2026-09-19 17:42:43 Functions: 40.0 % 5 2

            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              : !!***
        

Generated by: LCOV version 2.3-1