LCOV - code coverage report
Current view: top level - src/72_response - m_paral_pert.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 92.5 % 213 197
Test Date: 2026-09-19 17:42:43 Functions: 100.0 % 6 6

            Line data    Source code
       1              : !!****m* ABINIT/m_paral_pert
       2              : !! NAME
       3              : !!  m_paral_pert
       4              : !!
       5              : !! FUNCTION
       6              : !!  This module provides routines to manage the parallelisation/distribution
       7              : !!  over perturbations
       8              : !!
       9              : !! COPYRIGHT
      10              : !! Copyright (C) 2013-2026 ABINIT group (MT,FJ,MD)
      11              : !! This file is distributed under the terms of the
      12              : !! GNU General Public License, see ~abinit/COPYING
      13              : !! or http://www.gnu.org/copyleft/gpl.txt .
      14              : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt.
      15              : !!
      16              : !! SOURCE
      17              : 
      18              : #if defined HAVE_CONFIG_H
      19              : #include "config.h"
      20              : #endif
      21              : 
      22              : #include "abi_common.h"
      23              : 
      24              : MODULE m_paral_pert
      25              : 
      26              :  use defs_basis
      27              :  use m_abicore
      28              :  use m_errors
      29              :  use m_xmpi
      30              :  use m_dtset
      31              : 
      32              :  use defs_abitypes, only : MPI_type
      33              :  use m_time,      only : timab
      34              :  use m_copy,      only : deep_copy
      35              :  use m_paw_an,    only : paw_an_type, paw_an_free, paw_an_redistribute
      36              :  use m_paw_ij,    only : paw_ij_type, paw_ij_free, paw_ij_redistribute
      37              :  use m_pawfgrtab, only : pawfgrtab_type, pawfgrtab_free, pawfgrtab_redistribute
      38              :  use m_pawrhoij,  only : pawrhoij_type, pawrhoij_free, pawrhoij_redistribute
      39              :  use m_paral_atom,only : get_atm_proc
      40              :  use m_mpinfo,    only : initmpi_atom
      41              : 
      42              :  implicit none
      43              : 
      44              :  private
      45              : 
      46              : !public procedures.
      47              :  public :: set_pert_comm
      48              :  public :: unset_pert_comm
      49              :  public :: set_pert_paw
      50              :  public :: unset_pert_paw
      51              : 
      52              : !private procedures.
      53              :  private :: get_exchatom_list
      54              :  private :: get_exchatom_list1
      55              : !!***
      56              : 
      57              : CONTAINS
      58              : !!***
      59              : 
      60              : !----------------------------------------------------------------------
      61              : 
      62              : !!****f* m_paral_pert/set_pert_comm
      63              : !! NAME
      64              : !! set_pert_comm
      65              : !!
      66              : !! FUNCTION
      67              : !! Set the MPI communicators over the perturbed cell
      68              : !!
      69              : !! INPUTS
      70              : !!  nppert=number of processes for the parallelization over perturbations
      71              : !!
      72              : !! SIDE EFFECTS
      73              : !!  mpi_enreg=information about MPI parallelization
      74              : !!
      75              : !! SOURCE
      76              : 
      77          716 : subroutine set_pert_comm(mpi_enreg,nppert)
      78              : 
      79              : !Arguments ---------------------------------------------
      80              : !scalars
      81              :  integer,intent(in) :: nppert
      82              :  type(MPI_type), intent(inout) :: mpi_enreg
      83              : 
      84              : ! *************************************************************************
      85              : 
      86          716 :  if (mpi_enreg%paral_pert==0) return
      87              : 
      88              : !New communicators for the perturbed cell
      89           26 :  mpi_enreg%comm_cell =mpi_enreg%comm_cell_pert
      90           26 :  mpi_enreg%me_cell   =xmpi_comm_rank(mpi_enreg%comm_cell)
      91           26 :  mpi_enreg%nproc_cell=mpi_enreg%nproc/nppert
      92              : 
      93              : !Adjust other communicators
      94           26 :  mpi_enreg%comm_kpt    =mpi_enreg%comm_cell
      95           26 :  mpi_enreg%me_kpt      =mpi_enreg%me_cell
      96           26 :  mpi_enreg%comm_kptband=mpi_enreg%comm_cell
      97           26 :  mpi_enreg%comm_wvl    =mpi_enreg%comm_cell
      98              : 
      99              : end subroutine set_pert_comm
     100              : !!***
     101              : 
     102              : !----------------------------------------------------------------------
     103              : 
     104              : !!****f* m_paral_pert/unset_pert_comm
     105              : !! NAME
     106              : !! unset_pert_comm
     107              : !!
     108              : !! FUNCTION
     109              : !! Unset the MPI communicators over the perturbed cell; restore the global communicators.
     110              : !!
     111              : !! SIDE EFFECTS
     112              : !!  mpi_enreg=information about MPI parallelization
     113              : !!
     114              : !! SOURCE
     115              : 
     116          716 : subroutine unset_pert_comm(mpi_enreg)
     117              : 
     118              : !Arguments ---------------------------------------------
     119              : !scalars
     120              :  type(MPI_type), intent(inout) :: mpi_enreg
     121              : 
     122              : ! *************************************************************************
     123              : 
     124          716 :  if (mpi_enreg%paral_pert==0) return
     125              : 
     126              : !New communicators for the cell
     127           26 :  mpi_enreg%comm_cell =mpi_enreg%comm_world
     128           26 :  mpi_enreg%nproc_cell=mpi_enreg%nproc
     129           26 :  mpi_enreg%me_cell   =mpi_enreg%me
     130              : 
     131              : !Adjust other communicators
     132           26 :  mpi_enreg%comm_kpt    =mpi_enreg%comm_cell
     133           26 :  mpi_enreg%me_kpt      =mpi_enreg%me_cell
     134           26 :  mpi_enreg%comm_kptband=mpi_enreg%comm_cell
     135           26 :  mpi_enreg%comm_wvl    =mpi_enreg%comm_cell
     136              : 
     137              : end  subroutine unset_pert_comm
     138              : !!***
     139              : 
     140              : !----------------------------------------------------------------------
     141              : 
     142              : !!****f* m_paral_pert/set_pert_paw
     143              : !! NAME
     144              : !! set_pert_paw
     145              : !!
     146              : !! FUNCTION
     147              : !! Set PAW data for the parallelization over perturbations:
     148              : !!  Set MPI communicator over atomic sites
     149              : !!  Redistribute PAW on-site data
     150              : !!
     151              : !! INPUTS
     152              : !!  dtset <type(dataset_type)>=all input variables for this dataset
     153              : !!
     154              : !! OUTPUT
     155              : !!  paw_an_out(my_natom)<type(paw_an_type)>= --optional--
     156              : !!              redistributed PAW arrays given on angular mesh
     157              : !!              if not present, paw_an is redistributed "in-place"
     158              : !!  paw__ij_out(my_natom)<type(paw_ij_type)>= --optional--
     159              : !!              redistributed PAW arrays given on (i,j) channels
     160              : !!              if not present, paw_ij is redistributed "in-place"
     161              : !!  pawfgrtab_out(my_natom)<type(pawfgrtab_type)>= --optional--
     162              : !!              redistributed PAW atomic data given on fine grid
     163              : !!              if not present, pawfgrtab is redistributed "in-place"
     164              : !!  pawrhoij_out(my_natom)<type(pawrhoij_type)>= --optional--
     165              : !!              redistributed PAW rhoij occupancies
     166              : !!              if not present, pawrhoij is redistributed "in-place"
     167              : !!  old_atmtab=save the indexes of the atoms treated by current proc
     168              : !!  old_comm_atom=save the identifier of the MPI communicator
     169              : !!
     170              : !! SIDE EFFECTS
     171              : !!  mpi_enreg=information about MPI parallelization
     172              : !!  my_natom=number of atoms treated by current processor
     173              : !!  paw_an(my_natom)<type(paw_an_type)>=PAW arrays given on angular mesh
     174              : !!  paw_ij(my_natom)<type(paw_ij_type)>=PAW arrays given on (i,j) channels
     175              : !!  pawfgrtab(my_natom)<type(pawfgrtab_type)>=PAW atomic data given on fine grid
     176              : !!  pawrhoij(my_natom)<type(pawrhoij_type)>=PAW rhoij occupancies
     177              : !!
     178              : !! SOURCE
     179              : 
     180          716 : subroutine set_pert_paw(dtset,mpi_enreg,my_natom,old_atmtab,old_comm_atom,&
     181              : &                       paw_an,paw_ij,pawfgrtab,pawrhoij,&
     182              : &                       paw_an_out,paw_ij_out,pawfgrtab_out,pawrhoij_out)
     183              : 
     184              : !Arguments ---------------------------------------------
     185              : !scalars
     186              :  integer,intent(inout) :: my_natom
     187              :  integer,intent(inout) :: old_comm_atom
     188              :  type(dataset_type), intent(in) :: dtset
     189              :  type(MPI_type), intent(inout) :: mpi_enreg
     190              : !arrays
     191              :  integer,pointer,intent(out) :: old_atmtab(:)
     192              :  type(paw_ij_type),allocatable,target,intent(inout) :: paw_ij(:)
     193              :  type(paw_ij_type),optional,pointer,intent(inout) :: paw_ij_out(:)
     194              :  type(paw_an_type),allocatable,target,intent(inout) :: paw_an(:)
     195              :  type(paw_an_type),optional,pointer,intent(inout) :: paw_an_out(:)
     196              :  type(pawfgrtab_type),allocatable,target,intent(inout) :: pawfgrtab(:)
     197              :  type(pawfgrtab_type),optional,pointer,intent(inout) :: pawfgrtab_out(:)
     198              :  type(pawrhoij_type),allocatable,target,intent(inout) :: pawrhoij(:)
     199              :  type(pawrhoij_type),optional,pointer,intent(inout) :: pawrhoij_out(:)
     200              : 
     201              : !Local variables ---------------------------------------
     202              : !scalars
     203              : !Type of algo used for communications: 1-brute force, 2-asynchronous
     204              :  integer,parameter :: algo_option=2
     205              :  logical :: paral_atom
     206              : !arrays
     207          716 :  integer,allocatable :: SendAtomProc(:), SendAtomList(:)
     208          716 :  integer,allocatable :: RecvAtomProc(:), RecvAtomList(:)
     209              :  real(dp) :: tsec(2)
     210              : 
     211              : ! *************************************************************************
     212              : 
     213          716 :  call timab(593,1,tsec)
     214              : 
     215          716 :  paral_atom=(dtset%natom/=my_natom)
     216              : 
     217              : !Default value when parallelization over atomic sites is not activated
     218          716 :  if ((mpi_enreg%paral_pert==0).or.(.not.paral_atom).or.(dtset%usepaw==0)) then
     219          696 :    old_comm_atom=mpi_enreg%comm_atom
     220          696 :    call deep_copy(mpi_enreg%my_atmtab,old_atmtab)
     221          696 :    if (present(pawrhoij_out))  pawrhoij_out=>pawrhoij
     222          696 :    if (present(paw_ij_out))    paw_ij_out=>paw_ij
     223          696 :    if (present(paw_an_out))    paw_an_out=>paw_an
     224          696 :    if (present(pawfgrtab_out)) pawfgrtab_out=>pawfgrtab
     225              :    return
     226              :  end if
     227              : 
     228              : !Redefine communicator for atoms and store old communicator
     229              : 
     230           20 :  old_comm_atom=mpi_enreg%comm_atom
     231           20 :  call deep_copy(mpi_enreg%my_atmtab,old_atmtab)
     232           20 :  call initmpi_atom(dtset,mpi_enreg)
     233           20 :  my_natom=mpi_enreg%my_natom
     234              : 
     235              : !If "asynchronous algo", determine lists of atoms to be exchanged
     236              : !  between me and other processes
     237              :  if (algo_option==2) then
     238           20 :    call timab(594,1,tsec)
     239              :    call get_exchatom_list(old_comm_atom,mpi_enreg%comm_atom,old_atmtab,&
     240              : &       mpi_enreg%my_atmtab,dtset%natom,SendAtomProc,&
     241           20 : &       SendAtomList,RecvAtomProc,RecvAtomList)
     242           20 :    call timab(594,2,tsec)
     243              :  end if
     244              : 
     245              : !Redistribute PAW on-site data
     246              : 
     247              : !pawrhoij datastructure
     248           20 :  call timab(595,1,tsec)
     249           20 :  if (present(pawrhoij_out)) then
     250            0 :    nullify(pawrhoij_out)
     251              :    if (algo_option==1) then
     252              :      call pawrhoij_redistribute(pawrhoij,old_comm_atom,mpi_enreg%comm_atom,&
     253              : &         mpi_atmtab_in=old_atmtab,mpi_atmtab_out=mpi_enreg%my_atmtab,&
     254              : &         natom=dtset%natom,pawrhoij_out=pawrhoij_out)
     255              :    else if (algo_option==2) then
     256              :      call pawrhoij_redistribute(pawrhoij,old_comm_atom,mpi_enreg%comm_atom,&
     257              : &         mpi_atmtab_in=old_atmtab,mpi_atmtab_out=mpi_enreg%my_atmtab,&
     258              : &         natom=dtset%natom,pawrhoij_out=pawrhoij_out, &
     259              : &         SendAtomproc=SendAtomProc,SendAtomList=SendAtomList,&
     260            0 : &         RecvAtomProc=RecvAtomProc,RecvAtomList=RecvAtomList)
     261              :    end if
     262              :  else
     263              :    if (algo_option==1) then
     264              :      call pawrhoij_redistribute(pawrhoij,old_comm_atom,mpi_enreg%comm_atom,&
     265              : &         mpi_atmtab_in=old_atmtab,mpi_atmtab_out=mpi_enreg%my_atmtab,&
     266              : &         natom=dtset%natom)
     267           20 :    else if (algo_option==2) then
     268              :      call pawrhoij_redistribute(pawrhoij,old_comm_atom,mpi_enreg%comm_atom,&
     269              : &         mpi_atmtab_in=old_atmtab,mpi_atmtab_out=mpi_enreg%my_atmtab,&
     270              : &         natom=dtset%natom,&
     271              : &         SendAtomproc=SendAtomProc,SendAtomList=SendAtomList,&
     272              : &         RecvAtomProc=RecvAtomProc,RecvAtomList=RecvAtomList)
     273              :    end if
     274              :  end if
     275           20 :  call timab(595,2,tsec)
     276              : 
     277              : !paw_ij datastructure
     278           20 :  call timab(596,1,tsec)
     279           20 :  if (present(paw_ij_out)) then
     280            0 :    nullify(paw_ij_out)
     281              :    if (algo_option==1) then
     282              :      call paw_ij_redistribute(paw_ij,old_comm_atom,mpi_enreg%comm_atom,&
     283              : &         mpi_atmtab_in=old_atmtab,mpi_atmtab_out=mpi_enreg%my_atmtab,&
     284              : &         natom=dtset%natom,paw_ij_out=paw_ij_out)
     285              :    else if (algo_option==2) then
     286              :      call paw_ij_redistribute(paw_ij,old_comm_atom,mpi_enreg%comm_atom,&
     287              : &         mpi_atmtab_in=old_atmtab,mpi_atmtab_out=mpi_enreg%my_atmtab,&
     288              : &         natom=dtset%natom,paw_ij_out=paw_ij_out,&
     289              : &         SendAtomproc=SendAtomProc,SendAtomList=SendAtomList,&
     290            0 : &         RecvAtomProc=RecvAtomProc,RecvAtomList=RecvAtomList)
     291              :    end if
     292              :  else
     293              :    if (algo_option==1) then
     294              :      call paw_ij_redistribute(paw_ij,old_comm_atom,mpi_enreg%comm_atom,&
     295              : &         mpi_atmtab_in=old_atmtab,mpi_atmtab_out=mpi_enreg%my_atmtab,&
     296              : &         natom=dtset%natom)
     297           20 :    else if (algo_option==2) then
     298              :      call paw_ij_redistribute(paw_ij,old_comm_atom,mpi_enreg%comm_atom,&
     299              : &         mpi_atmtab_in=old_atmtab,mpi_atmtab_out=mpi_enreg%my_atmtab,&
     300              : &         natom=dtset%natom,&
     301              : &         SendAtomproc=SendAtomProc,SendAtomList=SendAtomList,&
     302              : &         RecvAtomProc=RecvAtomProc,RecvAtomList=RecvAtomList)
     303              :    end if
     304              :  end if
     305           20 :  call timab(596,2,tsec)
     306              : 
     307              : !paw_an datastructure
     308           20 :  call timab(597,1,tsec)
     309           20 :  if (present(paw_an_out)) then
     310            0 :    nullify(paw_an_out)
     311              :    if (algo_option==1) then
     312              :      call paw_an_redistribute(paw_an,old_comm_atom,mpi_enreg%comm_atom,&
     313              : &         mpi_atmtab_in=old_atmtab,mpi_atmtab_out=mpi_enreg%my_atmtab,&
     314              : &         natom=dtset%natom,paw_an_out=paw_an_out)
     315              :    else if (algo_option==2) then
     316              :      call paw_an_redistribute(paw_an,old_comm_atom,mpi_enreg%comm_atom,&
     317              : &         mpi_atmtab_in=old_atmtab,mpi_atmtab_out=mpi_enreg%my_atmtab,&
     318              : &         natom=dtset%natom,paw_an_out=paw_an_out,&
     319              : &         SendAtomproc=SendAtomProc,SendAtomList=SendAtomList,&
     320            0 : &         RecvAtomProc=RecvAtomProc,RecvAtomList=RecvAtomList)
     321              :    end if
     322              :  else
     323              :    if (algo_option==1) then
     324              :      call paw_an_redistribute(paw_an,old_comm_atom,mpi_enreg%comm_atom,&
     325              : &         mpi_atmtab_in=old_atmtab,mpi_atmtab_out=mpi_enreg%my_atmtab,&
     326              : &         natom=dtset%natom)
     327           20 :    else if (algo_option==2) then
     328              :      call paw_an_redistribute(paw_an,old_comm_atom,mpi_enreg%comm_atom,&
     329              : &         mpi_atmtab_in=old_atmtab,mpi_atmtab_out=mpi_enreg%my_atmtab,&
     330              : &         natom=dtset%natom,&
     331              : &         SendAtomproc=SendAtomProc,SendAtomList=SendAtomList,&
     332              : &         RecvAtomProc=RecvAtomProc,RecvAtomList=RecvAtomList)
     333              :    end if
     334              :  end if
     335           20 :  call timab(597,2,tsec)
     336              : 
     337              : !pawfgrtab datastructure
     338           20 :  call timab(598,1,tsec)
     339           20 :  if (present(pawfgrtab_out)) then
     340            0 :    nullify(pawfgrtab_out)
     341              :    if (algo_option==1) then
     342              :      call pawfgrtab_redistribute(pawfgrtab,old_comm_atom,mpi_enreg%comm_atom,&
     343              : &         mpi_atmtab_in=old_atmtab,mpi_atmtab_out=mpi_enreg%my_atmtab,&
     344              : &         natom=dtset%natom,pawfgrtab_out=pawfgrtab_out)
     345              :    else if (algo_option==2) then
     346              :      call pawfgrtab_redistribute(pawfgrtab,old_comm_atom,mpi_enreg%comm_atom,&
     347              : &         mpi_atmtab_in=old_atmtab,mpi_atmtab_out=mpi_enreg%my_atmtab,&
     348              : &         natom=dtset%natom,pawfgrtab_out=pawfgrtab_out,&
     349              : &         SendAtomproc=SendAtomProc,SendAtomList=SendAtomList,&
     350            0 : &         RecvAtomProc=RecvAtomProc,RecvAtomList=RecvAtomList)
     351              :    end if
     352              :  else
     353              :    if (algo_option==1) then
     354              :      call pawfgrtab_redistribute(pawfgrtab,old_comm_atom,mpi_enreg%comm_atom,&
     355              : &         mpi_atmtab_in=old_atmtab,mpi_atmtab_out=mpi_enreg%my_atmtab,&
     356              : &         natom=dtset%natom)
     357           20 :    else if (algo_option==2) then
     358              :      call pawfgrtab_redistribute(pawfgrtab,old_comm_atom,mpi_enreg%comm_atom,&
     359              : &         mpi_atmtab_in=old_atmtab,mpi_atmtab_out=mpi_enreg%my_atmtab,&
     360              : &         natom=dtset%natom,&
     361              : &         SendAtomproc=SendAtomProc,SendAtomList=SendAtomList,&
     362              : &         RecvAtomProc=RecvAtomProc,RecvAtomList=RecvAtomList)
     363              :    end if
     364              :  end if
     365           20 :  call timab(598,2,tsec)
     366              : 
     367              :  if (algo_option==2) then
     368           20 :    ABI_FREE(SendAtomProc)
     369           20 :    ABI_FREE(SendAtomList)
     370           20 :    ABI_FREE(RecvAtomProc)
     371           20 :    ABI_FREE(RecvAtomList)
     372              :  end if
     373              : 
     374           20 :  call timab(593,2,tsec)
     375              : 
     376              : end  subroutine set_pert_paw
     377              : !!***
     378              : 
     379              : !----------------------------------------------------------------------
     380              : 
     381              : !!****f* m_paral_pert/unset_pert_paw
     382              : !! NAME
     383              : !! unset_pert_paw
     384              : !!
     385              : !! FUNCTION
     386              : !! Unset PAW data after the parallelization over perturbations:
     387              : !!  Restore MPI communicator over atomic sites
     388              : !!  Restore PAW on-site data
     389              : !!
     390              : !! INPUTS
     391              : !!  dtset <type(dataset_type)>=all input variables for this dataset
     392              : !!  old_atmtab=index of atoms to restore
     393              : !!  old_comm_atom=MPI communicator to restore
     394              : !!  mpi_enreg=information about MPI parallelization
     395              : !!  my_natom=number of atoms treated by current processor
     396              : !!
     397              : !! OUTPUT
     398              : !!  paw_an_out(my_natom)<type(paw_an_type)>= --optional--
     399              : !!              redistributed PAW arrays given on angular mesh
     400              : !!              if not present, paw_an is restored "in-place"
     401              : !!  paw__ij_out(my_natom)<type(paw_ij_type)>= --optional--
     402              : !!              redistributed PAW arrays given on (i,j) channels
     403              : !!              if not present, paw_ij is restored "in-place"
     404              : !!  pawfgrtab_out(my_natom)<type(pawfgrtab_type)>= --optional--
     405              : !!              redistributed PAW atomic data given on fine grid
     406              : !!              if not present, pawfgrtab is restored "in-place"
     407              : !!  pawrhoij_out(my_natom)<type(pawrhoij_type)>= --optional--
     408              : !!              redistributed PAW rhoij occupancies
     409              : !!              if not present, pawrhoij is restored "in-place"
     410              : !! old_atmtab=save the indexes of atoms treated by current proc
     411              : !! old_comm_atom=save the identifier of the MPI communicator
     412              : !!
     413              : !! SIDE EFFECTS
     414              : !!  mpi_enreg=information about MPI parallelization
     415              : !!  my_natom=number of atoms treated by current processor
     416              : !!  paw_an(my_natom)<type(paw_an_type)>=PAW arrays given on angular mesh
     417              : !!  paw_ij(my_natom)<type(paw_ij_type)>=PAW arrays given on (i,j) channels
     418              : !!  pawfgrtab(my_natom)<type(pawfgrtab_type)>=PAW atomic data given on fine grid
     419              : !!  pawrhoij(my_natom)<type(pawrhoij_type)>=PAW rhoij occupancies
     420              : !!
     421              : !! SOURCE
     422              : 
     423          716 : subroutine unset_pert_paw(dtset,mpi_enreg,my_natom,old_atmtab,old_comm_atom,&
     424              : &                       paw_an,paw_ij,pawfgrtab,pawrhoij,&
     425              : &                       paw_an_out,paw_ij_out,pawfgrtab_out,pawrhoij_out)
     426              : 
     427              : !Arguments ---------------------------------------------
     428              : !scalars
     429              :  integer,intent(inout) :: my_natom
     430              :  integer,intent(inout) :: old_comm_atom
     431              :  type(dataset_type), intent(in) :: dtset
     432              :  type(MPI_type), intent(inout) :: mpi_enreg
     433              : !arrays
     434              :  integer,pointer,intent(inout) :: old_atmtab(:)
     435              :  type(paw_ij_type),allocatable,target,intent(inout) :: paw_ij(:)
     436              :  type(paw_ij_type),optional,pointer,intent(inout) :: paw_ij_out(:)
     437              :  type(paw_an_type),allocatable,target,intent(inout) :: paw_an(:)
     438              :  type(paw_an_type),optional,pointer,intent(inout) :: paw_an_out(:)
     439              :  type(pawfgrtab_type),allocatable,target,intent(inout) :: pawfgrtab(:)
     440              :  type(pawfgrtab_type),optional,pointer,intent(inout) :: pawfgrtab_out(:)
     441              :  type(pawrhoij_type),allocatable,target,intent(inout) :: pawrhoij(:)
     442              :  type(pawrhoij_type),optional,pointer,intent(inout) :: pawrhoij_out(:)
     443              : 
     444              : !Local variables ---------------------------------------
     445              : !scalars
     446              : !Type of algo used for communications: 1-brute force, 2-asynchronous
     447              :  integer,parameter :: algo_option=2
     448              : integer :: my_natom_old
     449              :  logical :: exchange,paral_atom
     450              : !arrays
     451          716 :  integer,allocatable :: SendAtomProc(:), SendAtomList(:)
     452          716 :  integer,allocatable :: RecvAtomProc(:), RecvAtomList(:)
     453              :  real(dp) :: tsec(2)
     454              : 
     455              : ! *************************************************************************
     456              : 
     457              : !Nothing to do when parallelization over atomic sites is not activated
     458          716 :  if ((mpi_enreg%paral_pert==0).or.(dtset%usepaw==0)) return
     459           20 :  if (.not.associated(old_atmtab)) return
     460           20 :  paral_atom=(dtset%natom/=size(old_atmtab))
     461           20 :  if (.not.paral_atom) return
     462              : 
     463              : !If "asynchronous algo", determine lists of atoms to be exchanged
     464              : !  between me and other processes
     465           20 :  exchange=.true.
     466              :  if (present(pawrhoij_out).and.present(paw_ij_out).and. &
     467           20 : &    present(paw_an_out)  .and.present(pawfgrtab_out)) exchange=.false.
     468              :  if (algo_option==2.and.exchange) then
     469           20 :    call timab(594,1,tsec)
     470           20 :    my_natom_old=size(old_atmtab)
     471              :    call get_exchatom_list1(mpi_enreg%comm_atom,old_comm_atom,mpi_enreg%my_atmtab,&
     472              : &       old_atmtab,dtset%natom,SendAtomProc,&
     473           20 : &       SendAtomList,RecvAtomProc,RecvAtomList)
     474           20 :    call timab(594,2,tsec)
     475              :  end if
     476              : 
     477              : !Redistribute PAW on-site data (if in-place storage)
     478              : !or destroy them (out-of-place storage)
     479              : 
     480              : !pawrhoij datastructure
     481           20 :  call timab(595,1,tsec)
     482           20 :  if (present(pawrhoij_out)) then
     483            0 :    call pawrhoij_free(pawrhoij_out)
     484            0 :    ABI_FREE(pawrhoij_out)
     485              :  else
     486              :    if (algo_option==1) then
     487              :      call pawrhoij_redistribute(pawrhoij,mpi_enreg%comm_atom,old_comm_atom,&
     488              : &         mpi_atmtab_in=mpi_enreg%my_atmtab,mpi_atmtab_out=old_atmtab,&
     489              : &         natom=dtset%natom)
     490           20 :    else if (algo_option==2) then
     491              :        call pawrhoij_redistribute(pawrhoij,mpi_enreg%comm_atom,old_comm_atom,&
     492              : &         mpi_atmtab_in=mpi_enreg%my_atmtab,mpi_atmtab_out=old_atmtab,&
     493              : &         natom=dtset%natom,&
     494              : &         SendAtomproc=SendAtomProc,SendAtomList=SendAtomList,&
     495              : &         RecvAtomProc=RecvAtomProc,RecvAtomList=RecvAtomList)
     496              :    end if
     497              :  end if
     498           20 :  call timab(595,2,tsec)
     499              : 
     500              : !paw_ij datastructure
     501           20 :  call timab(596,1,tsec)
     502           20 :  if (present(paw_ij_out)) then
     503            0 :    call paw_ij_free(paw_ij_out)
     504            0 :    ABI_FREE(paw_ij_out)
     505              :  else
     506              :    if (algo_option==1) then
     507              :      call paw_ij_redistribute(paw_ij,mpi_enreg%comm_atom,old_comm_atom,&
     508              : &         mpi_atmtab_in=mpi_enreg%my_atmtab,mpi_atmtab_out=old_atmtab,&
     509              : &         natom=dtset%natom)
     510           20 :    else if (algo_option==2) then
     511              :      call paw_ij_redistribute(paw_ij,mpi_enreg%comm_atom,old_comm_atom,&
     512              : &         mpi_atmtab_in=mpi_enreg%my_atmtab,mpi_atmtab_out=old_atmtab,&
     513              : &         natom=dtset%natom,&
     514              : &         SendAtomproc=SendAtomProc,SendAtomList=SendAtomList,&
     515              : &         RecvAtomProc=RecvAtomProc,RecvAtomList=RecvAtomList)
     516              :    end if
     517              :  end if
     518           20 :  call timab(596,2,tsec)
     519              : 
     520              : !paw_an datastructure
     521           20 :  call timab(597,1,tsec)
     522           20 :  if (present(paw_an_out)) then
     523            0 :    call paw_an_free(paw_an_out)
     524            0 :    ABI_FREE(paw_an_out)
     525              :  else
     526              :    if (algo_option==1) then
     527              :      call paw_an_redistribute(paw_an,mpi_enreg%comm_atom,old_comm_atom,&
     528              : &         mpi_atmtab_in=mpi_enreg%my_atmtab,mpi_atmtab_out=old_atmtab,&
     529              : &         natom=dtset%natom)
     530           20 :    else if (algo_option==2) then
     531              :      call paw_an_redistribute(paw_an,mpi_enreg%comm_atom,old_comm_atom,&
     532              : &         mpi_atmtab_in=mpi_enreg%my_atmtab,mpi_atmtab_out=old_atmtab,&
     533              : &         natom=dtset%natom,&
     534              : &         SendAtomproc=SendAtomProc,SendAtomList=SendAtomList,&
     535              : &         RecvAtomProc=RecvAtomProc,RecvAtomList=RecvAtomList)
     536              :    end if
     537              :  end if
     538           20 :  call timab(597,2,tsec)
     539              : 
     540              : !pawfgrtab datastructure
     541           20 :  call timab(598,1,tsec)
     542           20 :  if (present(pawfgrtab_out)) then
     543            0 :    call pawfgrtab_free(pawfgrtab_out)
     544            0 :    ABI_FREE(pawfgrtab_out)
     545              :  else
     546              :    if (algo_option==1) then
     547              :      call pawfgrtab_redistribute(pawfgrtab,mpi_enreg%comm_atom,old_comm_atom,&
     548              : &         mpi_atmtab_in=mpi_enreg%my_atmtab,mpi_atmtab_out=old_atmtab,&
     549              : &         natom=dtset%natom)
     550           20 :    else if (algo_option==2) then
     551              :      call pawfgrtab_redistribute(pawfgrtab,mpi_enreg%comm_atom,old_comm_atom,&
     552              : &         mpi_atmtab_in=mpi_enreg%my_atmtab,mpi_atmtab_out=old_atmtab,&
     553              : &         natom=dtset%natom,&
     554              : &         SendAtomproc=SendAtomProc,SendAtomList=SendAtomList,&
     555              : &         RecvAtomProc=RecvAtomProc,RecvAtomList=RecvAtomList)
     556              :    end if
     557              :  end if
     558           20 :  call timab(598,2,tsec)
     559              : 
     560              : !Release some memory
     561           20 :  if (algo_option==2.and.exchange) then
     562           20 :    ABI_FREE(SendAtomProc)
     563           20 :    ABI_FREE(SendAtomList)
     564           20 :    ABI_FREE(RecvAtomProc)
     565           20 :    ABI_FREE(RecvAtomList)
     566              :  end if
     567              : 
     568              : !Restore communicator for atoms
     569           20 :  ABI_FREE(old_atmtab)
     570           20 :  old_comm_atom=mpi_enreg%comm_atom
     571           20 :  call deep_copy(mpi_enreg%my_atmtab,old_atmtab)
     572           20 :  call initmpi_atom(dtset,mpi_enreg)
     573           20 :  my_natom=mpi_enreg%my_natom
     574              : 
     575           20 : end  subroutine unset_pert_paw
     576              : !!***
     577              : 
     578              : !----------------------------------------------------------------------
     579              : 
     580              : !!****f* m_paral_atom/get_exchatom_list
     581              : !! NAME
     582              : !! get_exchatom_list
     583              : !!
     584              : !! FUNCTION
     585              : !! This routine determine the list of atoms to be exchanged by current process and other processes.
     586              : !! The initial communicator (mpicomm_in) should be a common ancestor of (mpicomm_in and mpicomm_out);
     587              : !! It is splitted in "nbgroup" final communicators (mpicomm_out).
     588              : !!
     589              : !! INPUTS
     590              : !!  mpicomm_in=input MPI communicator (over atoms) among which atoms are initially distributed
     591              : !!  mpicomm_out=MPI communicator (over atoms) among which we want to distribute atoms
     592              : !!  my_atmtab_in= Index of atoms initially treated by current proc (communicator mpicomm_in)
     593              : !!  my_atmtab_out= Index of atoms finally treated by current proc (communicator mpicomm_out)
     594              : !!  natom = total number of atoms
     595              : !!  nbgroup = # of mpicomm_out communicators included in mpicomm_in
     596              : !!
     597              : !! OUTPUT
     598              : !! For current proc :
     599              : !! RecvAtomProc(:)= rank of processor from which I expect atom (in mpicomm_in)
     600              : !! RecvAtomList(:)= indexes of atoms to be received by me
     601              : !!   RecvAtomList(irecv) are the atoms I expect from RecvAtomProc(irecv)
     602              : !! SendAtomProc(:)= ranks of process destination of atom (in mpicomm_in)
     603              : !! SendAtomList(:)= indexes of atoms to be sent by me
     604              : !!   SendAtomList(isend) are the atoms sent to SendAtomProc(isend)
     605              : !!
     606              : !! SOURCE
     607              : 
     608              : 
     609           20 :  subroutine get_exchatom_list(mpicomm_in,mpicomm_out,my_atmtab_in,my_atmtab_out,natom, &
     610              : &                             SendAtomProc,SendAtomList,RecvAtomProc,RecvAtomList)
     611              : 
     612              : !Arguments ---------------------------------------------
     613              : !scalars
     614              :  integer,intent(in) :: mpicomm_in,mpicomm_out,natom
     615              : !arrays
     616              :  integer,intent(in) :: my_atmtab_in(:),my_atmtab_out(:)
     617              :  integer,allocatable,intent(out) :: RecvAtomProc(:),RecvAtomList(:)
     618              :  integer,allocatable,intent(out) :: SendAtomList(:),SendAtomProc(:)
     619              : 
     620              : !Local variables ---------------------------------------
     621              : !scalars
     622              :  integer :: igroup,i1,ierr,ii,me_in,me_in_out,me_out,me_out0_in
     623              :  integer :: my_natom_in,my_natom_out,nbgroup,nbsend,nproc_in,nproc_max,nproc_out
     624              : !arrays
     625              :  integer :: buf_int(3),rank0(1),ranks0_out_in(1)
     626           20 :  integer, allocatable :: buf_int_all(:),group(:),master_commout(:),procs(:),ranks(:)
     627           20 :  integer, allocatable  :: ranks1(:,:),sizecomm(:)
     628              : 
     629              : ! *************************************************************************
     630              : 
     631           20 :  nproc_in=xmpi_comm_size(mpicomm_in)
     632           20 :  me_in=xmpi_comm_rank(mpicomm_in)
     633           20 :  my_natom_in=size(my_atmtab_in)
     634           20 :  nproc_out=xmpi_comm_size(mpicomm_out)
     635           20 :  me_out=xmpi_comm_rank(mpicomm_out)
     636           20 :  my_natom_out=size(my_atmtab_out)
     637              : 
     638           20 :  rank0(1)=0
     639           20 :  call xmpi_comm_translate_ranks(mpicomm_out,1,rank0(1),mpicomm_in,ranks0_out_in(1))
     640           20 :  me_out0_in=ranks0_out_in(1)
     641              : 
     642           60 :  ABI_MALLOC(ranks,(1:nproc_in))
     643           40 :  ABI_MALLOC(sizecomm,(1:nproc_in))
     644           40 :  ABI_MALLOC(master_commout,(1:nproc_in))
     645           60 :  ABI_MALLOC(group,(0:nproc_in-1))
     646           20 :  buf_int(1)=me_out; buf_int(2)=me_out0_in; buf_int(3)=nproc_out;
     647              : 
     648           60 :  ABI_MALLOC(buf_int_all,(3*nproc_in))
     649           20 :  call xmpi_allgather(buf_int,3,buf_int_all,mpicomm_in,ierr)
     650           20 :  nbgroup=0;
     651           20 :  nproc_max=0
     652          400 :  ranks(:)=-1;group(:)=-1;sizecomm(:)=-1;master_commout(:)=-1
     653              : 
     654          100 :  do ii=1,nproc_in
     655           80 :    ranks(ii)=buf_int_all(3*ii-2)    !me_out
     656           80 :    master_commout(ii)=buf_int_all(3*ii-1) !rank of me_out=0 of mpicomm_out expressed in mpicomm_in
     657              : 
     658          100 :    if (ranks(ii)==0) then
     659           36 :      nbgroup=nbgroup+1
     660           36 :      sizecomm(nbgroup)=buf_int_all(3*ii) !nproc_out
     661           36 :      group(master_commout(ii))=nbgroup
     662           36 :      if (sizecomm(nbgroup)>nproc_max) nproc_max=sizecomm(nbgroup)
     663              :    end if
     664              : 
     665              :  enddo
     666           20 :  ABI_FREE(buf_int_all)
     667              : 
     668              : 
     669           80 :  ABI_MALLOC(ranks1,(nbgroup,0:nproc_max-1))
     670          148 :  ranks1(:,:)=-1
     671          100 :  do ii=1,nproc_in
     672           80 :    me_in_out=ranks(ii)
     673           80 :    igroup=group(master_commout(ii))
     674          100 :    ranks1(igroup,me_in_out)=ii-1 !numbering of procs
     675              :  enddo
     676              : 
     677              : !Send
     678           20 :  nbsend=0
     679           20 :  if (my_natom_in>0) then
     680           30 :    ABI_MALLOC(SendAtomList,(my_natom_in*nbgroup))
     681           20 :    ABI_MALLOC(SendAtomProc,(my_natom_in*nbgroup))
     682           30 :    ABI_MALLOC(procs,(my_natom_in))
     683           28 :    do igroup=1,nbgroup
     684           18 :      call get_atm_proc(my_atmtab_in,natom,sizecomm(igroup),procs)
     685           46 :      do i1=1,my_natom_in
     686           18 :        nbsend=nbsend+1
     687           18 :        SendAtomProc(nbsend)=ranks1(igroup,procs(i1))
     688           36 :        SendAtomList(nbsend)=my_atmtab_in(i1)
     689              :      end do
     690              :    end do
     691           10 :    ABI_FREE(procs)
     692              :  else
     693           10 :   ABI_MALLOC(SendAtomList,(0))
     694           10 :   ABI_MALLOC(SendAtomProc,(0))
     695              : end if
     696              : 
     697              : !recv
     698           20 :  if (my_natom_out>0) then !no return before because of xmpi_allgather and of the sending operation
     699           54 :    ABI_MALLOC(RecvAtomProc,(my_natom_out))
     700           36 :    ABI_MALLOC(RecvAtomList,(my_natom_out))
     701           36 :    RecvAtomList(:)=my_atmtab_out(:)
     702              : !the atoms are put in increasing order,see get_my_atmtab so the procs are sorted by growing process
     703           18 :    call get_atm_proc(RecvAtomList,natom,nproc_in,RecvAtomProc)
     704              :  else
     705            2 :    ABI_MALLOC(RecvAtomList,(0))
     706            2 :    ABI_MALLOC(RecvAtomProc,(0))
     707              :  end if
     708              : 
     709           20 :  ABI_FREE(master_commout)
     710           20 :  ABI_FREE(ranks1)
     711           20 :  ABI_FREE(group)
     712           20 :  ABI_FREE(ranks)
     713           20 :  ABI_FREE(sizecomm)
     714              : 
     715           20 : end subroutine get_exchatom_list
     716              : !!***
     717              : 
     718              : !----------------------------------------------------------------------
     719              : 
     720              : !!****f* m_paral_atom/get_exchatom_list1
     721              : !! NAME
     722              : !! get_exchatom_list1
     723              : !!
     724              : !! FUNCTION
     725              : !! This routine determine the list of atoms to be exchanged by current process and other processes.
     726              : !! this function redistribute the atoms of one mpicomm_in among mpicomm_out
     727              : !!
     728              : !! INPUTS
     729              : !!  mpicomm_in=input MPI communicator (over atoms) among which atoms are initially distributed
     730              : !!  mpicomm_out=MPI communicator (over atoms) among which we want to distribute atoms
     731              : !!  my_atmtab_in= Index of atoms initially treated by current proc (communicator mpicomm_in)
     732              : !!  my_atmtab_out= Index of atoms finally treated by current proc (communicator mpicomm_out)
     733              : !!  natom = total number of atoms
     734              : !!
     735              : !! OUTPUT
     736              : !! For current proc:
     737              : !! RecvAtomProc(:)= rank of processor from which I expect atom (in mpicomm_out)
     738              : !! RecvAtomList(:)= indexes of atoms to be received by me
     739              : !!   RecvAtomList(irecv) are the atoms I expect from RecvAtomProc(irecv)
     740              : !! SendAtomProc(:)= ranks of process destination of atom (in mpicomm_out)
     741              : !! SendAtomList(:)= indexes of atoms to be sent by me
     742              : !!   SendAtomList(isend) are the atoms sent to SendAtomProc(isend)
     743              : !!
     744              : !! NOTES
     745              : !! Previously mpicomm_out has be split in several mpicomm_in.
     746              : !! In our purpose, we only need to redistribute the atoms of one mpicomm_in among mpicomm_out
     747              : !! because all structures of atoms we have to exchange have the same value in each mpicomm_in.
     748              : !! The mpicomm_in we choose is the one in which the processor 0 of mpicomm_out belong
     749              : !!
     750              : !! SOURCE
     751              : 
     752           20 : subroutine get_exchatom_list1(mpicomm_in,mpicomm_out,my_atmtab_in,my_atmtab_out,natom, &
     753              : &                             SendAtomProc,SendAtomList,RecvAtomProc,RecvAtomList)
     754              : 
     755              : !Arguments ---------------------------------------------
     756              : !scalars
     757              :  integer,intent(in) :: mpicomm_in,mpicomm_out,natom
     758              : !arrays
     759              :  integer,intent(in) :: my_atmtab_in(:),my_atmtab_out(:)
     760              :  integer,allocatable,intent(out) :: RecvAtomProc(:),RecvAtomList(:)
     761              :  integer,allocatable,intent(out) :: SendAtomList(:),SendAtomProc(:)
     762              : 
     763              : !Local variables ---------------------------------------
     764              : !scalars
     765              :  integer :: i1,ier,me_out,my_natom_in,my_natom_out,nproc_in,nproc_out
     766              :  logical :: sender
     767              : !arrays
     768           20 :  integer,allocatable :: ranks_in(:),ranks_in_out(:)
     769              : 
     770              : ! *************************************************************************
     771              : 
     772           20 :  me_out=xmpi_comm_rank(mpicomm_out)
     773           20 :  my_natom_in=size(my_atmtab_in)
     774           20 :  nproc_out=xmpi_comm_size(mpicomm_out)
     775           20 :  my_natom_out=size(my_atmtab_out)
     776           20 :  nproc_in=xmpi_comm_size(mpicomm_in)
     777              : 
     778           20 :  call xmpi_bcast(nproc_in,0,mpicomm_out,ier)
     779           60 :  ABI_MALLOC(ranks_in_out,(0:nproc_in-1))
     780              : 
     781              : !All atoms are distributed among each mpicomm_in
     782              : !redistribute the atoms of one mpicomm_in among mpicomm_out
     783              : 
     784              : !Look for the communicator mpicomm_in from which me_out=0 belong
     785              : !Get ranks of all processors of mpicomm_in expressed in mpicomm_out
     786           20 :  if (me_out==0) then
     787           10 :    ABI_MALLOC(ranks_in,(0:nproc_in-1))
     788           51 :    ranks_in=(/ (i1,i1=0,nproc_in-1 )/)
     789            5 :    call xmpi_comm_translate_ranks(mpicomm_in,nproc_in,ranks_in,mpicomm_out,ranks_in_out)
     790            5 :    ABI_FREE(ranks_in)
     791              :  end if
     792           20 :  call xmpi_bcast(ranks_in_out,0,mpicomm_out,ier)
     793              : 
     794              : !Check if me_out is one of the sending proc.
     795              : !(ie belongs to the mpicomm_in from which me_out belong)
     796           20 :  sender = .false.
     797           46 :  do i1=0,nproc_in-1
     798           46 :    if (me_out==ranks_in_out(i1)) then
     799              :      sender = .true.
     800              :      exit
     801              :    end if
     802              :  end do
     803              : 
     804              : !Send
     805           20 :  if (my_natom_in>0.and.sender) then
     806           30 :    ABI_MALLOC(SendAtomList,(my_natom_in))
     807           20 :    ABI_MALLOC(SendAtomProc,(my_natom_in))
     808           20 :    SendAtomList(:)=my_atmtab_in(:)
     809              : !  The atoms are put in increasing order,see get_my_atmtab
     810              : !  so the procs are sorted by growing process
     811           10 :    call get_atm_proc(SendAtomList,natom,nproc_out,SendAtomProc)
     812              :  else
     813           10 :    ABI_MALLOC(SendAtomList,(0))
     814           10 :    ABI_MALLOC(SendAtomProc,(0))
     815              :  end if
     816              : 
     817              : !Recv
     818           20 :  if (my_natom_out>0) then
     819           30 :    ABI_MALLOC(RecvAtomProc,(my_natom_out))
     820           20 :    ABI_MALLOC(RecvAtomList,(my_natom_out))
     821           20 :    RecvAtomList(:)=my_atmtab_out(:)
     822              : !  The atoms are put in increasing order,see get_my_atmtab
     823              : !  so the procs are sorted by growing process
     824           10 :    call get_atm_proc(RecvAtomList,natom,nproc_in,RecvAtomProc)
     825           20 :    RecvAtomProc(:)=ranks_in_out(RecvAtomProc(:))
     826              :  else
     827           10 :    ABI_MALLOC(RecvAtomList,(0))
     828           10 :    ABI_MALLOC(RecvAtomProc,(0))
     829              :  end if
     830              : 
     831           20 :  ABI_FREE(ranks_in_out)
     832              : 
     833           20 : end subroutine get_exchatom_list1
     834              : !!***
     835              : 
     836              : !----------------------------------------------------------------------
     837              : 
     838              : END MODULE m_paral_pert
     839              : !!***
        

Generated by: LCOV version 2.3-1