45    type(mpi_grp_t) :: mpi_grp
 
   47    integer, 
allocatable :: rdispls(:)
 
   48    integer, 
allocatable :: sdispls(:)
 
   49    integer, 
allocatable :: rcounts(:)
 
   50    integer, 
allocatable :: scounts(:)
 
   72    part_out, nsend, nrec, order_in, order_out, inverse)
 
   73    type(partition_transfer_t), 
intent(out) :: this
 
   74    integer,                    
intent(in)  :: np
 
   75    integer(int64),                
intent(in)  :: global_index(:)
 
   76    type(mpi_grp_t), 
target,    
intent(in)  :: mpi_grp_in
 
   77    type(mpi_grp_t), 
target,    
intent(in)  :: mpi_grp_out
 
   78    integer,                    
intent(in)  :: part_out(:)
 
   79    integer,                    
intent(out) :: nsend
 
   80    integer,                    
intent(out) :: nrec
 
   81    integer(int64), 
allocatable,   
intent(out) :: order_in(:)
 
   82    integer(int64), 
allocatable,   
intent(out) :: order_out(:)
 
   83    logical, 
optional,          
intent(in)  :: inverse
 
   85    logical :: found, inverse_
 
   86    integer :: n12, tmp_partno(2), ipart, opart, ip, pcount, mycolumn, irec, isend, ipos
 
   87    type(iihash_t) :: map_out
 
   88    type(mpi_grp_t), 
pointer :: grp1, grp2
 
   89    integer, 
allocatable :: partno_list(:,:), part_map(:,:)
 
   98    if (mpi_grp_in%size >= mpi_grp_out%size) 
then 
  109    if (mod(grp1%size, grp2%size) /= 0) 
then 
  110      message(1) = 
"Incompatible size of mpi groups in partition_transfer_init" 
  113    n12 = grp1%size/grp2%size
 
  117    safe_allocate(partno_list(1:2, 1:grp1%size))
 
  118    tmp_partno(1) = grp1%rank + 1
 
  119    tmp_partno(2) = grp2%rank + 1
 
  120    call this%mpi_grp%allgather(tmp_partno(1), 2, mpi_integer, partno_list(1, 1), 2, mpi_integer)
 
  128    safe_allocate(part_map(1:grp2%size, 1:n12))
 
  130    do ipart = 1, grp2%size
 
  133        if (partno_list(2, ip) == ipart) 
then 
  136          if (pcount > n12 .or. any(partno_list(1, ip) == part_map(1:ipart,:))) 
then 
  137            message(1) = 
"Incompatible mpi groups in partition_transfer_init" 
  140          part_map(ipart, pcount) = partno_list(1, ip)
 
  141          if (ip == grp1%rank + 1) mycolumn = pcount
 
  144      if (pcount /= n12) 
then 
  145        message(1) = 
"Incompatible mpi groups in partition_transfer_init" 
  163    if (.not. inverse_) 
then 
  164      do ipart = 1, grp2%size
 
  165        if (mpi_grp_in%size >= mpi_grp_out%size) 
then 
  170          call iihash_insert(map_out, part_map(ipart, mycolumn), part_map(ipart, mycolumn))
 
  174      do ipart = 1, grp2%size
 
  175        if (mpi_grp_in%size >= mpi_grp_out%size) 
then 
  177            call iihash_insert(map_out, part_map(ipart, ip), part_map(ipart, ip))
 
  180          call iihash_insert(map_out, part_map(ipart, mycolumn), ipart)
 
  185    if (.not. inverse_) 
then 
  188      do irec = 1, grp1%size
 
  190        if (.not. found) cycle
 
  191        nsend = nsend + count(part_out(1:np) == opart)
 
  196      do isend = 1, grp1%size
 
  198        if (.not. found) cycle
 
  199        nrec = nrec + count(part_out(1:np) == opart)
 
  204    safe_allocate(this%sdispls(1:grp1%size))
 
  205    safe_allocate(this%scounts(1:grp1%size))
 
  207    safe_allocate(this%rdispls(1:grp1%size))
 
  208    safe_allocate(this%rcounts(1:grp1%size))
 
  210    if (.not. inverse_) 
then 
  211      safe_allocate(order_in(1:max(1,nsend)))
 
  215      do irec = 1, grp1%size
 
  216        this%scounts(irec) = 0
 
  217        this%sdispls(irec) = ipos
 
  220        if (.not. found) cycle
 
  224          if (part_out(ip) == opart) 
then 
  226            order_in(ipos) = global_index(ip)
 
  227            this%scounts(irec) = this%scounts(irec) + 1
 
  233      safe_allocate(order_out(1:max(1,nrec)))
 
  237      do isend = 1, grp1%size
 
  238        this%rcounts(isend) = 0
 
  239        this%rdispls(isend) = ipos
 
  242        if (.not. found) cycle
 
  246          if (part_out(ip) == opart) 
then 
  248            order_out(ipos) = global_index(ip)
 
  249            this%rcounts(isend) = this%rcounts(isend) + 1
 
  256    safe_deallocate_a(part_map)
 
  257    safe_deallocate_a(partno_list)
 
  260    if (.not. inverse_) 
then 
  262      call this%mpi_grp%alltoall(this%scounts, 1, mpi_integer, &
 
  263        this%rcounts, 1, mpi_integer)
 
  265      do isend = 1, grp1%size
 
  266        this%rdispls(isend) = nrec
 
  267        nrec = nrec + this%rcounts(isend)
 
  271      call this%mpi_grp%alltoall(this%rcounts, 1, mpi_integer, &
 
  272        this%scounts, 1, mpi_integer)
 
  274      do irec = 1, grp1%size
 
  275        this%sdispls(irec) = nsend
 
  276        nsend = nsend + this%scounts(irec)
 
  280    if (.not. inverse_) 
then 
  282      safe_allocate(order_out(1:max(1,nrec)))
 
  283      call this%mpi_grp%alltoallv(order_in, this%scounts, this%sdispls, mpi_integer8, &
 
  284        order_out, this%rcounts, this%rdispls, mpi_integer8)
 
  287      safe_allocate(order_in(1:max(1,nsend)))
 
  288      call this%mpi_grp%alltoallv(order_out, this%rcounts, this%rdispls, mpi_integer8, &
 
  289        order_in, this%scounts, this%sdispls, mpi_integer8)
 
  301    safe_deallocate_a(this%rdispls)
 
  302    safe_deallocate_a(this%sdispls)
 
  303    safe_deallocate_a(this%rcounts)
 
  304    safe_deallocate_a(this%scounts)
 
  311#include "partition_transfer_inc.F90" 
  314#include "complex.F90" 
  315#include "partition_transfer_inc.F90" 
This module implements a simple hash table for non-negative integer keys and integer values.
 
subroutine, public iihash_end(h)
Free a hash table.
 
subroutine, public iihash_insert(h, key, val)
Insert a (key, val) pair into the hash table h.
 
integer function, public iihash_lookup(h, key, found)
Look up a value in the hash table h. If found is present, it indicates if key could be found in the t...
 
subroutine, public iihash_init(h)
Initialize a hash table h.
 
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
 
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
 
subroutine mpi_grp_copy(mpi_grp_out, mpi_grp_in)
 
subroutine, public partition_transfer_init(this, np, global_index, mpi_grp_in, mpi_grp_out, part_out, nsend, nrec, order_in, order_out, inverse)
initialize the partition transfer object
 
subroutine, public partition_transfer_end(this)
 
subroutine, public zpartition_transfer(this, f_in, f_out)
 
subroutine, public dpartition_transfer(this, f_in, f_out)
 
The partition transfer object ensures that during a mesh transfer points are associated to the correc...