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...