xref: /petsc/src/dm/impls/swarm/data_ex.c (revision 5ff6d247539c86491dc822dc7e845e819e6cc4a3)
1095059a4SDave May /*
2095059a4SDave May Build a few basic tools to help with partitioned domains.
3095059a4SDave May 
4095059a4SDave May 1)
5095059a4SDave May On each processor, have a DomainExchangerTopology.
6095059a4SDave May This is a doubly-connected edge list which enumerates the
7095059a4SDave May communication paths between connected processors. By numbering
8da81f932SPierre Jolivet these paths we can always uniquely assign message identifiers.
9095059a4SDave May 
10095059a4SDave May         edge
11095059a4SDave May          10
12095059a4SDave May proc  --------->  proc
13095059a4SDave May  0    <--------    1
14095059a4SDave May          11
15095059a4SDave May         twin
16095059a4SDave May 
172d4ee042Sprj- Eg: Proc 0 send to proc 1 with message id is 10. To receive the correct
18095059a4SDave May message, proc 1 looks for the edge connected to proc 0, and then the
192d4ee042Sprj- message id comes from the twin of that edge
20095059a4SDave May 
21095059a4SDave May 2)
22095059a4SDave May A DomainExchangerArrayPacker.
23095059a4SDave May A little function which given a piece of data, will memcpy the data into
24095059a4SDave May an array (which will be sent to procs) into the correct place.
25095059a4SDave May 
26095059a4SDave May On Proc 1 we sent data to procs 0,2,3. The data is on different lengths.
27095059a4SDave May All data gets jammed into single array. Need to "jam" data into correct locations
28095059a4SDave May The Packer knows how much is to going to each processor and keeps track of the inserts
29095059a4SDave May so as to avoid ever packing TOO much into one slot, and inevatbly corrupting some memory
30095059a4SDave May 
31095059a4SDave May data to 0    data to 2       data to 3
32095059a4SDave May 
33095059a4SDave May |--------|-----------------|--|
34095059a4SDave May 
35095059a4SDave May User has to unpack message themselves. I can get you the pointer for each i
36095059a4SDave May entry, but you'll have to cast it to the appropriate data type.
37095059a4SDave May 
38095059a4SDave May Phase A: Build topology
39095059a4SDave May 
40095059a4SDave May Phase B: Define message lengths
41095059a4SDave May 
42095059a4SDave May Phase C: Pack data
43095059a4SDave May 
44095059a4SDave May Phase D: Send data
45095059a4SDave May 
462064fc68SDave May + Constructor
4777048351SPatrick Sanan DMSwarmDataExCreate()
482064fc68SDave May + Phase A
4977048351SPatrick Sanan DMSwarmDataExTopologyInitialize()
5077048351SPatrick Sanan DMSwarmDataExTopologyAddNeighbour()
5177048351SPatrick Sanan DMSwarmDataExTopologyAddNeighbour()
5277048351SPatrick Sanan DMSwarmDataExTopologyFinalize()
532064fc68SDave May + Phase B
5477048351SPatrick Sanan DMSwarmDataExZeroAllSendCount()
5577048351SPatrick Sanan DMSwarmDataExAddToSendCount()
5677048351SPatrick Sanan DMSwarmDataExAddToSendCount()
5777048351SPatrick Sanan DMSwarmDataExAddToSendCount()
582064fc68SDave May + Phase C
5977048351SPatrick Sanan DMSwarmDataExPackInitialize()
6077048351SPatrick Sanan DMSwarmDataExPackData()
6177048351SPatrick Sanan DMSwarmDataExPackData()
6277048351SPatrick Sanan DMSwarmDataExPackFinalize()
632064fc68SDave May +Phase D
6477048351SPatrick Sanan DMSwarmDataExBegin()
652064fc68SDave May  ... perform any calculations ...
6677048351SPatrick Sanan DMSwarmDataExEnd()
67095059a4SDave May 
682064fc68SDave May ... user calls any getters here ...
69095059a4SDave May 
70095059a4SDave May */
71095059a4SDave May #include <petscvec.h>
72095059a4SDave May #include <petscmat.h>
736497c311SBarry Smith #include <petsc/private/petscimpl.h>
74095059a4SDave May 
75279f676cSBarry Smith #include "../src/dm/impls/swarm/data_ex.h"
76095059a4SDave May 
77095059a4SDave May const char *status_names[] = {"initialized", "finalized", "unknown"};
78095059a4SDave May 
79ed923d71SDave May PETSC_EXTERN PetscLogEvent DMSWARM_DataExchangerTopologySetup;
80ed923d71SDave May PETSC_EXTERN PetscLogEvent DMSWARM_DataExchangerBegin;
81ed923d71SDave May PETSC_EXTERN PetscLogEvent DMSWARM_DataExchangerEnd;
82ed923d71SDave May PETSC_EXTERN PetscLogEvent DMSWARM_DataExchangerSendCount;
83ed923d71SDave May PETSC_EXTERN PetscLogEvent DMSWARM_DataExchangerPack;
84095059a4SDave May 
DMSwarmDataExCreate(MPI_Comm comm,const PetscInt count,DMSwarmDataEx * ex)85d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExCreate(MPI_Comm comm, const PetscInt count, DMSwarmDataEx *ex)
86d71ae5a4SJacob Faibussowitsch {
8777048351SPatrick Sanan   DMSwarmDataEx d;
88095059a4SDave May 
89521f74f9SMatthew G. Knepley   PetscFunctionBegin;
909566063dSJacob Faibussowitsch   PetscCall(PetscNew(&d));
919566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_dup(comm, &d->comm));
929566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(d->comm, &d->rank));
93095059a4SDave May 
94095059a4SDave May   d->instance = count;
95095059a4SDave May 
96095059a4SDave May   d->topology_status        = DEOBJECT_STATE_UNKNOWN;
97095059a4SDave May   d->message_lengths_status = DEOBJECT_STATE_UNKNOWN;
98095059a4SDave May   d->packer_status          = DEOBJECT_STATE_UNKNOWN;
99095059a4SDave May   d->communication_status   = DEOBJECT_STATE_UNKNOWN;
100095059a4SDave May 
101095059a4SDave May   d->n_neighbour_procs = -1;
102095059a4SDave May   d->neighbour_procs   = NULL;
103095059a4SDave May 
104095059a4SDave May   d->messages_to_be_sent      = NULL;
105095059a4SDave May   d->message_offsets          = NULL;
106095059a4SDave May   d->messages_to_be_recvieved = NULL;
107095059a4SDave May 
10878c64234SJose E. Roman   d->unit_message_size   = (size_t)-1;
109095059a4SDave May   d->send_message        = NULL;
110095059a4SDave May   d->send_message_length = -1;
111095059a4SDave May   d->recv_message        = NULL;
112095059a4SDave May   d->recv_message_length = -1;
113095059a4SDave May   d->total_pack_cnt      = -1;
114095059a4SDave May   d->pack_cnt            = NULL;
115095059a4SDave May 
116095059a4SDave May   d->send_tags = NULL;
117095059a4SDave May   d->recv_tags = NULL;
118095059a4SDave May 
119095059a4SDave May   d->_stats    = NULL;
120095059a4SDave May   d->_requests = NULL;
121521f74f9SMatthew G. Knepley   *ex          = d;
1223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
123095059a4SDave May }
124095059a4SDave May 
125298827fbSBarry Smith /*
1269dddd249SSatish Balay     This code is horrible, who let it get into main.
127298827fbSBarry Smith 
128298827fbSBarry Smith     Should be printing to a viewer, should not be using PETSC_COMM_WORLD
129298827fbSBarry Smith 
130298827fbSBarry Smith */
DMSwarmDataExView(DMSwarmDataEx d)131d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExView(DMSwarmDataEx d)
132d71ae5a4SJacob Faibussowitsch {
133095059a4SDave May   PetscMPIInt p;
134095059a4SDave May 
135095059a4SDave May   PetscFunctionBegin;
13663a3b9bcSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "DMSwarmDataEx: instance=%" PetscInt_FMT "\n", d->instance));
1379566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "  topology status:        %s \n", status_names[d->topology_status]));
1389566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "  message lengths status: %s \n", status_names[d->message_lengths_status]));
1399566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "  packer status status:   %s \n", status_names[d->packer_status]));
1409566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "  communication status:   %s \n", status_names[d->communication_status]));
141095059a4SDave May 
142095059a4SDave May   if (d->topology_status == DEOBJECT_FINALIZED) {
1439566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "  Topology:\n"));
1449566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD, "    [%d] neighbours: %d \n", d->rank, d->n_neighbour_procs));
14548a46eb9SPierre Jolivet     for (p = 0; p < d->n_neighbour_procs; p++) PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD, "    [%d]   neighbour[%d] = %d \n", d->rank, p, d->neighbour_procs[p]));
1469566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD, stdout));
147095059a4SDave May   }
148298827fbSBarry Smith 
149095059a4SDave May   if (d->message_lengths_status == DEOBJECT_FINALIZED) {
1509566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "  Message lengths:\n"));
1519566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD, "    [%d] atomic size: %ld \n", d->rank, (long int)d->unit_message_size));
1523a7d0413SPierre Jolivet     for (p = 0; p < d->n_neighbour_procs; p++) PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD, "    [%d] >>>>> ( %" PetscInt_FMT " units :: tag = %d) >>>>> [%d] \n", d->rank, d->messages_to_be_sent[p], d->send_tags[p], d->neighbour_procs[p]));
153095059a4SDave May     for (p = 0; p < d->n_neighbour_procs; p++) {
15463a3b9bcSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD, "    [%d] <<<<< ( %" PetscInt_FMT " units :: tag = %d) <<<<< [%d] \n", d->rank, d->messages_to_be_recvieved[p], d->recv_tags[p], d->neighbour_procs[p]));
155095059a4SDave May     }
1569566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD, stdout));
157095059a4SDave May   }
1583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
159095059a4SDave May }
160095059a4SDave May 
DMSwarmDataExDestroy(DMSwarmDataEx d)161d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExDestroy(DMSwarmDataEx d)
162d71ae5a4SJacob Faibussowitsch {
163095059a4SDave May   PetscFunctionBegin;
1649566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_free(&d->comm));
1659566063dSJacob Faibussowitsch   if (d->neighbour_procs) PetscCall(PetscFree(d->neighbour_procs));
1669566063dSJacob Faibussowitsch   if (d->messages_to_be_sent) PetscCall(PetscFree(d->messages_to_be_sent));
1679566063dSJacob Faibussowitsch   if (d->message_offsets) PetscCall(PetscFree(d->message_offsets));
1689566063dSJacob Faibussowitsch   if (d->messages_to_be_recvieved) PetscCall(PetscFree(d->messages_to_be_recvieved));
1699566063dSJacob Faibussowitsch   if (d->send_message) PetscCall(PetscFree(d->send_message));
1709566063dSJacob Faibussowitsch   if (d->recv_message) PetscCall(PetscFree(d->recv_message));
1719566063dSJacob Faibussowitsch   if (d->pack_cnt) PetscCall(PetscFree(d->pack_cnt));
1729566063dSJacob Faibussowitsch   if (d->send_tags) PetscCall(PetscFree(d->send_tags));
1739566063dSJacob Faibussowitsch   if (d->recv_tags) PetscCall(PetscFree(d->recv_tags));
1749566063dSJacob Faibussowitsch   if (d->_stats) PetscCall(PetscFree(d->_stats));
1759566063dSJacob Faibussowitsch   if (d->_requests) PetscCall(PetscFree(d->_requests));
1769566063dSJacob Faibussowitsch   PetscCall(PetscFree(d));
1773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
178095059a4SDave May }
179095059a4SDave May 
180095059a4SDave May /* === Phase A === */
181095059a4SDave May 
DMSwarmDataExTopologyInitialize(DMSwarmDataEx d)182d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExTopologyInitialize(DMSwarmDataEx d)
183d71ae5a4SJacob Faibussowitsch {
184095059a4SDave May   PetscFunctionBegin;
185095059a4SDave May   d->topology_status   = DEOBJECT_INITIALIZED;
186095059a4SDave May   d->n_neighbour_procs = 0;
1879566063dSJacob Faibussowitsch   PetscCall(PetscFree(d->neighbour_procs));
1889566063dSJacob Faibussowitsch   PetscCall(PetscFree(d->messages_to_be_sent));
1899566063dSJacob Faibussowitsch   PetscCall(PetscFree(d->message_offsets));
1909566063dSJacob Faibussowitsch   PetscCall(PetscFree(d->messages_to_be_recvieved));
1919566063dSJacob Faibussowitsch   PetscCall(PetscFree(d->pack_cnt));
1929566063dSJacob Faibussowitsch   PetscCall(PetscFree(d->send_tags));
1939566063dSJacob Faibussowitsch   PetscCall(PetscFree(d->recv_tags));
1943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
195095059a4SDave May }
196095059a4SDave May 
DMSwarmDataExTopologyAddNeighbour(DMSwarmDataEx d,const PetscMPIInt proc_id)197d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExTopologyAddNeighbour(DMSwarmDataEx d, const PetscMPIInt proc_id)
198d71ae5a4SJacob Faibussowitsch {
199095059a4SDave May   PetscMPIInt n, found;
200d7d19db6SBarry Smith   PetscMPIInt size;
201095059a4SDave May 
202095059a4SDave May   PetscFunctionBegin;
20308401ef6SPierre Jolivet   PetscCheck(d->topology_status != DEOBJECT_FINALIZED, d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology has been finalized. To modify or update call DMSwarmDataExTopologyInitialize() first");
204f7d195e4SLawrence Mitchell   PetscCheck(d->topology_status == DEOBJECT_INITIALIZED, d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology must be initialised. Call DMSwarmDataExTopologyInitialize() first");
2052064fc68SDave May 
206095059a4SDave May   /* error on negative entries */
20708401ef6SPierre Jolivet   PetscCheck(proc_id >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Trying to set proc neighbour with a rank < 0");
208095059a4SDave May   /* error on ranks larger than number of procs in communicator */
2099566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(d->comm, &size));
21008401ef6SPierre Jolivet   PetscCheck(proc_id < size, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Trying to set proc neighbour %d with a rank >= size %d", proc_id, size);
2119566063dSJacob Faibussowitsch   if (d->n_neighbour_procs == 0) PetscCall(PetscMalloc1(1, &d->neighbour_procs));
212095059a4SDave May   /* check for proc_id */
213095059a4SDave May   found = 0;
214095059a4SDave May   for (n = 0; n < d->n_neighbour_procs; n++) {
215ad540459SPierre Jolivet     if (d->neighbour_procs[n] == proc_id) found = 1;
216095059a4SDave May   }
217095059a4SDave May   if (found == 0) { /* add it to list */
2189566063dSJacob Faibussowitsch     PetscCall(PetscRealloc(sizeof(PetscMPIInt) * (d->n_neighbour_procs + 1), &d->neighbour_procs));
219095059a4SDave May     d->neighbour_procs[d->n_neighbour_procs] = proc_id;
220095059a4SDave May     d->n_neighbour_procs++;
221095059a4SDave May   }
2223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
223095059a4SDave May }
224095059a4SDave May 
225095059a4SDave May /*
226095059a4SDave May counter: the index of the communication object
227095059a4SDave May N: the number of processors
228095059a4SDave May r0: rank of sender
229095059a4SDave May r1: rank of receiver
230095059a4SDave May 
231095059a4SDave May procs = { 0, 1, 2, 3 }
232095059a4SDave May 
233095059a4SDave May 0 ==> 0         e=0
234095059a4SDave May 0 ==> 1         e=1
235095059a4SDave May 0 ==> 2         e=2
236095059a4SDave May 0 ==> 3         e=3
237095059a4SDave May 
238095059a4SDave May 1 ==> 0         e=4
239095059a4SDave May 1 ==> 1         e=5
240095059a4SDave May 1 ==> 2         e=6
241095059a4SDave May 1 ==> 3         e=7
242095059a4SDave May 
243095059a4SDave May 2 ==> 0         e=8
244095059a4SDave May 2 ==> 1         e=9
245095059a4SDave May 2 ==> 2         e=10
246095059a4SDave May 2 ==> 3         e=11
247095059a4SDave May 
248095059a4SDave May 3 ==> 0         e=12
249095059a4SDave May 3 ==> 1         e=13
250095059a4SDave May 3 ==> 2         e=14
251095059a4SDave May 3 ==> 3         e=15
252095059a4SDave May 
253095059a4SDave May If we require that proc A sends to proc B, then the SEND tag index will be given by
254095059a4SDave May   N * rank(A) + rank(B) + offset
255095059a4SDave May If we require that proc A will receive from proc B, then the RECV tag index will be given by
256095059a4SDave May   N * rank(B) + rank(A) + offset
257095059a4SDave May 
258095059a4SDave May */
_get_tags(PetscInt counter,PetscMPIInt N,PetscMPIInt r0,PetscMPIInt r1,PetscMPIInt maxtag,PetscMPIInt * _st,PetscMPIInt * _rt)25952c42f6eSMatthew G. Knepley static void _get_tags(PetscInt counter, PetscMPIInt N, PetscMPIInt r0, PetscMPIInt r1, PetscMPIInt maxtag, PetscMPIInt *_st, PetscMPIInt *_rt)
260d71ae5a4SJacob Faibussowitsch {
261095059a4SDave May   PetscMPIInt st, rt;
262095059a4SDave May 
26352c42f6eSMatthew G. Knepley   st   = (N * r0 + r1 + N * N * counter) % maxtag;
26452c42f6eSMatthew G. Knepley   rt   = (N * r1 + r0 + N * N * counter) % maxtag;
265095059a4SDave May   *_st = st;
266095059a4SDave May   *_rt = rt;
267095059a4SDave May }
268095059a4SDave May 
269095059a4SDave May /*
270095059a4SDave May Makes the communication map symmetric
271095059a4SDave May */
DMSwarmDataExCompleteCommunicationMap_Private(MPI_Comm comm,PetscMPIInt n,const PetscMPIInt proc_neighbours[],PetscMPIInt * n_new,PetscMPIInt ** proc_neighbours_new)27266976f2fSJacob Faibussowitsch static PetscErrorCode DMSwarmDataExCompleteCommunicationMap_Private(MPI_Comm comm, PetscMPIInt n, const PetscMPIInt proc_neighbours[], PetscMPIInt *n_new, PetscMPIInt **proc_neighbours_new)
273d71ae5a4SJacob Faibussowitsch {
274dcf43ee8SDave May   Mat                A;
275095059a4SDave May   PetscInt           i, j, nc;
276095059a4SDave May   PetscInt           n_, *proc_neighbours_;
277e4fbd051SBarry Smith   PetscInt           rank_;
278e4fbd051SBarry Smith   PetscMPIInt        size, rank;
279095059a4SDave May   PetscScalar       *vals;
280095059a4SDave May   const PetscInt    *cols;
281095059a4SDave May   const PetscScalar *red_vals;
282095059a4SDave May   PetscMPIInt        _n_new, *_proc_neighbours_new;
283095059a4SDave May 
284095059a4SDave May   PetscFunctionBegin;
285095059a4SDave May   n_ = n;
28666976f2fSJacob Faibussowitsch   PetscCall(PetscMalloc1(n_, &proc_neighbours_));
287ad540459SPierre Jolivet   for (i = 0; i < n_; ++i) proc_neighbours_[i] = proc_neighbours[i];
2889566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
2899566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
290e4fbd051SBarry Smith   rank_ = rank;
291095059a4SDave May 
2929566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, &A));
2939566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(A, PETSC_DECIDE, PETSC_DECIDE, size, size));
2949566063dSJacob Faibussowitsch   PetscCall(MatSetType(A, MATAIJ));
2959566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(A, 1, NULL));
2969566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(A, n_, NULL, n_, NULL));
2979566063dSJacob Faibussowitsch   PetscCall(MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
298095059a4SDave May   /* Build original map */
2999566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n_, &vals));
300ad540459SPierre Jolivet   for (i = 0; i < n_; ++i) vals[i] = 1.0;
3019566063dSJacob Faibussowitsch   PetscCall(MatSetValues(A, 1, &rank_, n_, proc_neighbours_, vals, INSERT_VALUES));
3029566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(A, MAT_FLUSH_ASSEMBLY));
3039566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(A, MAT_FLUSH_ASSEMBLY));
304095059a4SDave May   /* Now force all other connections if they are not already there */
305095059a4SDave May   /* It's more efficient to do them all at once */
306ad540459SPierre Jolivet   for (i = 0; i < n_; ++i) vals[i] = 2.0;
3079566063dSJacob Faibussowitsch   PetscCall(MatSetValues(A, n_, proc_neighbours_, 1, &rank_, vals, INSERT_VALUES));
3089566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
3099566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
3106275818cSDave May   /*
3119566063dSJacob Faibussowitsch   PetscCall(PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD,PETSC_VIEWER_ASCII_INFO));
3129566063dSJacob Faibussowitsch   PetscCall(MatView(A,PETSC_VIEWER_STDOUT_WORLD));
3139566063dSJacob Faibussowitsch   PetscCall(PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD));
3146275818cSDave May */
315095059a4SDave May   if ((n_new != NULL) && (proc_neighbours_new != NULL)) {
3169566063dSJacob Faibussowitsch     PetscCall(MatGetRow(A, rank_, &nc, &cols, &red_vals));
317835f2295SStefano Zampini     PetscCall(PetscMPIIntCast(nc, &_n_new));
3189566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(_n_new, &_proc_neighbours_new));
319835f2295SStefano Zampini     for (j = 0; j < nc; ++j) PetscCall(PetscMPIIntCast(cols[j], &_proc_neighbours_new[j]));
3209566063dSJacob Faibussowitsch     PetscCall(MatRestoreRow(A, rank_, &nc, &cols, &red_vals));
321835f2295SStefano Zampini     *n_new               = _n_new;
322835f2295SStefano Zampini     *proc_neighbours_new = _proc_neighbours_new;
323095059a4SDave May   }
3249566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&A));
3259566063dSJacob Faibussowitsch   PetscCall(PetscFree(vals));
3269566063dSJacob Faibussowitsch   PetscCall(PetscFree(proc_neighbours_));
3279566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Barrier(comm));
3283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
329095059a4SDave May }
330095059a4SDave May 
DMSwarmDataExTopologyFinalize(DMSwarmDataEx d)331d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExTopologyFinalize(DMSwarmDataEx d)
332d71ae5a4SJacob Faibussowitsch {
333*b8b5be36SMartin Diehl   PetscMPIInt symm_nn = 0, *symm_procs = NULL, r0, n, st, rt, size, *maxtag, iflg;
334095059a4SDave May 
335095059a4SDave May   PetscFunctionBegin;
33608401ef6SPierre Jolivet   PetscCheck(d->topology_status == DEOBJECT_INITIALIZED, d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology must be initialised. Call DMSwarmDataExTopologyInitialize() first");
3372064fc68SDave May 
3389566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_DataExchangerTopologySetup, 0, 0, 0, 0));
339a5b23f4aSJose E. Roman   /* given information about all my neighbours, make map symmetric */
34066976f2fSJacob Faibussowitsch   PetscCall(DMSwarmDataExCompleteCommunicationMap_Private(d->comm, d->n_neighbour_procs, d->neighbour_procs, &symm_nn, &symm_procs));
341095059a4SDave May   /* update my arrays */
3429566063dSJacob Faibussowitsch   PetscCall(PetscFree(d->neighbour_procs));
343095059a4SDave May   d->n_neighbour_procs = symm_nn;
344095059a4SDave May   d->neighbour_procs   = symm_procs;
345095059a4SDave May   /* allocates memory */
3469566063dSJacob Faibussowitsch   if (!d->messages_to_be_sent) PetscCall(PetscMalloc1(d->n_neighbour_procs + 1, &d->messages_to_be_sent));
3479566063dSJacob Faibussowitsch   if (!d->message_offsets) PetscCall(PetscMalloc1(d->n_neighbour_procs + 1, &d->message_offsets));
3489566063dSJacob Faibussowitsch   if (!d->messages_to_be_recvieved) PetscCall(PetscMalloc1(d->n_neighbour_procs + 1, &d->messages_to_be_recvieved));
3499566063dSJacob Faibussowitsch   if (!d->pack_cnt) PetscCall(PetscMalloc(sizeof(PetscInt) * d->n_neighbour_procs, &d->pack_cnt));
3509566063dSJacob Faibussowitsch   if (!d->_stats) PetscCall(PetscMalloc(sizeof(MPI_Status) * 2 * d->n_neighbour_procs, &d->_stats));
3519566063dSJacob Faibussowitsch   if (!d->_requests) PetscCall(PetscMalloc(sizeof(MPI_Request) * 2 * d->n_neighbour_procs, &d->_requests));
3529566063dSJacob Faibussowitsch   if (!d->send_tags) PetscCall(PetscMalloc(sizeof(int) * d->n_neighbour_procs, &d->send_tags));
3539566063dSJacob Faibussowitsch   if (!d->recv_tags) PetscCall(PetscMalloc(sizeof(int) * d->n_neighbour_procs, &d->recv_tags));
354095059a4SDave May   /* compute message tags */
3559566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(d->comm, &size));
356*b8b5be36SMartin Diehl   PetscCallMPI(MPI_Comm_get_attr(MPI_COMM_WORLD, MPI_TAG_UB, &maxtag, &iflg));
357*b8b5be36SMartin Diehl   PetscCheck(iflg, d->comm, PETSC_ERR_LIB, "MPI error: MPI_Comm_get_attr() is not returning a MPI_TAG_UB");
358095059a4SDave May   r0 = d->rank;
359521f74f9SMatthew G. Knepley   for (n = 0; n < d->n_neighbour_procs; ++n) {
360095059a4SDave May     PetscMPIInt r1 = d->neighbour_procs[n];
361095059a4SDave May 
36252c42f6eSMatthew G. Knepley     _get_tags(d->instance, size, r0, r1, *maxtag, &st, &rt);
363835f2295SStefano Zampini     d->send_tags[n] = st;
364835f2295SStefano Zampini     d->recv_tags[n] = rt;
365095059a4SDave May   }
366095059a4SDave May   d->topology_status = DEOBJECT_FINALIZED;
3679566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_DataExchangerTopologySetup, 0, 0, 0, 0));
3683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
369095059a4SDave May }
370095059a4SDave May 
371095059a4SDave May /* === Phase B === */
_DMSwarmDataExConvertProcIdToLocalIndex(DMSwarmDataEx de,PetscMPIInt proc_id,PetscMPIInt * local)37266976f2fSJacob Faibussowitsch static PetscErrorCode _DMSwarmDataExConvertProcIdToLocalIndex(DMSwarmDataEx de, PetscMPIInt proc_id, PetscMPIInt *local)
373d71ae5a4SJacob Faibussowitsch {
374095059a4SDave May   PetscMPIInt i, np;
375095059a4SDave May 
376095059a4SDave May   PetscFunctionBegin;
377095059a4SDave May   np     = de->n_neighbour_procs;
378095059a4SDave May   *local = -1;
379521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
380095059a4SDave May     if (proc_id == de->neighbour_procs[i]) {
381095059a4SDave May       *local = i;
382095059a4SDave May       break;
383095059a4SDave May     }
384095059a4SDave May   }
3853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
386095059a4SDave May }
387095059a4SDave May 
DMSwarmDataExInitializeSendCount(DMSwarmDataEx de)388d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExInitializeSendCount(DMSwarmDataEx de)
389d71ae5a4SJacob Faibussowitsch {
390095059a4SDave May   PetscMPIInt i;
391095059a4SDave May 
392095059a4SDave May   PetscFunctionBegin;
39308401ef6SPierre Jolivet   PetscCheck(de->topology_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Topology not finalized");
3949566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_DataExchangerSendCount, 0, 0, 0, 0));
395095059a4SDave May   de->message_lengths_status = DEOBJECT_INITIALIZED;
396ad540459SPierre Jolivet   for (i = 0; i < de->n_neighbour_procs; ++i) de->messages_to_be_sent[i] = 0;
3973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
398095059a4SDave May }
399095059a4SDave May 
400095059a4SDave May /*
401095059a4SDave May 1) only allows counters to be set on neighbouring cpus
402095059a4SDave May */
DMSwarmDataExAddToSendCount(DMSwarmDataEx de,const PetscMPIInt proc_id,const PetscInt count)403d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExAddToSendCount(DMSwarmDataEx de, const PetscMPIInt proc_id, const PetscInt count)
404d71ae5a4SJacob Faibussowitsch {
405095059a4SDave May   PetscMPIInt local_val;
406095059a4SDave May 
407095059a4SDave May   PetscFunctionBegin;
40808401ef6SPierre Jolivet   PetscCheck(de->message_lengths_status != DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths have been defined. To modify these call DMSwarmDataExInitializeSendCount() first");
409f7d195e4SLawrence Mitchell   PetscCheck(de->message_lengths_status == DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths must be defined. Call DMSwarmDataExInitializeSendCount() first");
4102064fc68SDave May 
4119566063dSJacob Faibussowitsch   PetscCall(_DMSwarmDataExConvertProcIdToLocalIndex(de, proc_id, &local_val));
41208401ef6SPierre Jolivet   PetscCheck(local_val != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Proc %d is not a valid neighbour rank", (int)proc_id);
4132064fc68SDave May 
414095059a4SDave May   de->messages_to_be_sent[local_val] = de->messages_to_be_sent[local_val] + count;
4153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
416095059a4SDave May }
417095059a4SDave May 
DMSwarmDataExFinalizeSendCount(DMSwarmDataEx de)418d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExFinalizeSendCount(DMSwarmDataEx de)
419d71ae5a4SJacob Faibussowitsch {
420095059a4SDave May   PetscFunctionBegin;
42108401ef6SPierre Jolivet   PetscCheck(de->message_lengths_status == DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths must be defined. Call DMSwarmDataExInitializeSendCount() first");
4222064fc68SDave May 
423095059a4SDave May   de->message_lengths_status = DEOBJECT_FINALIZED;
4249566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_DataExchangerSendCount, 0, 0, 0, 0));
4253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
426095059a4SDave May }
427095059a4SDave May 
428095059a4SDave May /* === Phase C === */
429095059a4SDave May /*
4305627991aSBarry Smith   zero out all send counts
4315627991aSBarry Smith   free send and recv buffers
4325627991aSBarry Smith   zeros out message length
4335627991aSBarry Smith   zeros out all counters
4345627991aSBarry Smith   zero out packed data counters
435095059a4SDave May */
_DMSwarmDataExInitializeTmpStorage(DMSwarmDataEx de)43666976f2fSJacob Faibussowitsch static PetscErrorCode _DMSwarmDataExInitializeTmpStorage(DMSwarmDataEx de)
437d71ae5a4SJacob Faibussowitsch {
438095059a4SDave May   PetscMPIInt i, np;
439095059a4SDave May 
440095059a4SDave May   PetscFunctionBegin;
441095059a4SDave May   np = de->n_neighbour_procs;
442521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
443095059a4SDave May     /*  de->messages_to_be_sent[i] = -1; */
444095059a4SDave May     de->messages_to_be_recvieved[i] = -1;
445095059a4SDave May   }
4469566063dSJacob Faibussowitsch   PetscCall(PetscFree(de->send_message));
4479566063dSJacob Faibussowitsch   PetscCall(PetscFree(de->recv_message));
4483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
449095059a4SDave May }
450095059a4SDave May 
451095059a4SDave May /*
4525627991aSBarry Smith    Zeros out pack data counters
4535627991aSBarry Smith    Ensures mesaage length is set
4545627991aSBarry Smith    Checks send counts properly initialized
4555627991aSBarry Smith    allocates space for pack data
456095059a4SDave May */
DMSwarmDataExPackInitialize(DMSwarmDataEx de,size_t unit_message_size)457d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExPackInitialize(DMSwarmDataEx de, size_t unit_message_size)
458d71ae5a4SJacob Faibussowitsch {
459095059a4SDave May   PetscMPIInt i, np;
460095059a4SDave May   PetscInt    total;
461095059a4SDave May 
462095059a4SDave May   PetscFunctionBegin;
46308401ef6SPierre Jolivet   PetscCheck(de->topology_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Topology not finalized");
46408401ef6SPierre Jolivet   PetscCheck(de->message_lengths_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths not finalized");
4659566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_DataExchangerPack, 0, 0, 0, 0));
466095059a4SDave May   de->packer_status = DEOBJECT_INITIALIZED;
4679566063dSJacob Faibussowitsch   PetscCall(_DMSwarmDataExInitializeTmpStorage(de));
468095059a4SDave May   np                    = de->n_neighbour_procs;
469095059a4SDave May   de->unit_message_size = unit_message_size;
470095059a4SDave May   total                 = 0;
471521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
472095059a4SDave May     if (de->messages_to_be_sent[i] == -1) {
473095059a4SDave May       PetscMPIInt proc_neighour = de->neighbour_procs[i];
474835f2295SStefano Zampini       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ORDER, "Messages_to_be_sent[neighbour_proc=%d] is un-initialised. Call DMSwarmDataExSetSendCount() first", proc_neighour);
475095059a4SDave May     }
476095059a4SDave May     total = total + de->messages_to_be_sent[i];
477095059a4SDave May   }
478095059a4SDave May   /* create space for the data to be sent */
4799566063dSJacob Faibussowitsch   PetscCall(PetscMalloc(unit_message_size * (total + 1), &de->send_message));
480095059a4SDave May   /* initialize memory */
4819566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(de->send_message, unit_message_size * (total + 1)));
482095059a4SDave May   /* set total items to send */
483095059a4SDave May   de->send_message_length = total;
484095059a4SDave May   de->message_offsets[0]  = 0;
485095059a4SDave May   total                   = de->messages_to_be_sent[0];
486521f74f9SMatthew G. Knepley   for (i = 1; i < np; ++i) {
487095059a4SDave May     de->message_offsets[i] = total;
488095059a4SDave May     total                  = total + de->messages_to_be_sent[i];
489095059a4SDave May   }
490095059a4SDave May   /* init the packer counters */
491095059a4SDave May   de->total_pack_cnt = 0;
492ad540459SPierre Jolivet   for (i = 0; i < np; ++i) de->pack_cnt[i] = 0;
4933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
494095059a4SDave May }
495095059a4SDave May 
496095059a4SDave May /*
4975627991aSBarry Smith     Ensures data gets been packed appropriately and no overlaps occur
498095059a4SDave May */
DMSwarmDataExPackData(DMSwarmDataEx de,PetscMPIInt proc_id,PetscInt n,void * data)499d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExPackData(DMSwarmDataEx de, PetscMPIInt proc_id, PetscInt n, void *data)
500d71ae5a4SJacob Faibussowitsch {
501095059a4SDave May   PetscMPIInt local;
502095059a4SDave May   PetscInt    insert_location;
503095059a4SDave May   void       *dest;
504095059a4SDave May 
505095059a4SDave May   PetscFunctionBegin;
50608401ef6SPierre Jolivet   PetscCheck(de->packer_status != DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Packed data have been defined. To modify these call DMSwarmDataExInitializeSendCount(), DMSwarmDataExAddToSendCount(), DMSwarmDataExPackInitialize() first");
507f7d195e4SLawrence Mitchell   PetscCheck(de->packer_status == DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Packed data must be defined. Call DMSwarmDataExInitializeSendCount(), DMSwarmDataExAddToSendCount(), DMSwarmDataExPackInitialize() first");
5082064fc68SDave May 
50928b400f6SJacob Faibussowitsch   PetscCheck(de->send_message, de->comm, PETSC_ERR_ORDER, "send_message is not initialized. Call DMSwarmDataExPackInitialize() first");
5109566063dSJacob Faibussowitsch   PetscCall(_DMSwarmDataExConvertProcIdToLocalIndex(de, proc_id, &local));
511835f2295SStefano Zampini   PetscCheck(local != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "proc_id %d is not registered neighbour", proc_id);
512835f2295SStefano Zampini   PetscCheck(n + de->pack_cnt[local] <= de->messages_to_be_sent[local], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Trying to pack too many entries to be sent to proc %d. Space requested = %" PetscInt_FMT ": Attempt to insert %" PetscInt_FMT, proc_id, de->messages_to_be_sent[local], n + de->pack_cnt[local]);
5132064fc68SDave May 
514095059a4SDave May   /* copy memory */
515095059a4SDave May   insert_location = de->message_offsets[local] + de->pack_cnt[local];
516095059a4SDave May   dest            = ((char *)de->send_message) + de->unit_message_size * insert_location;
5179566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(dest, data, de->unit_message_size * n));
518095059a4SDave May   /* increment counter */
519095059a4SDave May   de->pack_cnt[local] = de->pack_cnt[local] + n;
5203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
521095059a4SDave May }
522095059a4SDave May 
523095059a4SDave May /*
524095059a4SDave May *) Ensures all data has been packed
525095059a4SDave May */
DMSwarmDataExPackFinalize(DMSwarmDataEx de)526d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExPackFinalize(DMSwarmDataEx de)
527d71ae5a4SJacob Faibussowitsch {
528095059a4SDave May   PetscMPIInt i, np;
529095059a4SDave May   PetscInt    total;
530095059a4SDave May 
531095059a4SDave May   PetscFunctionBegin;
53208401ef6SPierre Jolivet   PetscCheck(de->packer_status == DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Packer has not been initialized. Must call DMSwarmDataExPackInitialize() first.");
533095059a4SDave May   np = de->n_neighbour_procs;
534521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
535835f2295SStefano Zampini     PetscCheck(de->pack_cnt[i] == de->messages_to_be_sent[i], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not all messages for neighbour[%d] have been packed. Expected %" PetscInt_FMT " : Inserted %" PetscInt_FMT, de->neighbour_procs[i], de->messages_to_be_sent[i], de->pack_cnt[i]);
536095059a4SDave May   }
537095059a4SDave May   /* init */
538ad540459SPierre Jolivet   for (i = 0; i < np; ++i) de->messages_to_be_recvieved[i] = -1;
539095059a4SDave May   /* figure out the recv counts here */
5406497c311SBarry Smith   for (i = 0; i < np; ++i) PetscCallMPI(MPIU_Isend(&de->messages_to_be_sent[i], 1, MPIU_INT, de->neighbour_procs[i], de->send_tags[i], de->comm, &de->_requests[i]));
5416497c311SBarry Smith   for (i = 0; i < np; ++i) PetscCallMPI(MPIU_Irecv(&de->messages_to_be_recvieved[i], 1, MPIU_INT, de->neighbour_procs[i], de->recv_tags[i], de->comm, &de->_requests[np + i]));
5429566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Waitall(2 * np, de->_requests, de->_stats));
543095059a4SDave May   /* create space for the data to be recvieved */
544095059a4SDave May   total = 0;
545ad540459SPierre Jolivet   for (i = 0; i < np; ++i) total = total + de->messages_to_be_recvieved[i];
5469566063dSJacob Faibussowitsch   PetscCall(PetscMalloc(de->unit_message_size * (total + 1), &de->recv_message));
547095059a4SDave May   /* initialize memory */
5489566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(de->recv_message, de->unit_message_size * (total + 1)));
5492d4ee042Sprj-   /* set total items to receive */
550095059a4SDave May   de->recv_message_length  = total;
551095059a4SDave May   de->packer_status        = DEOBJECT_FINALIZED;
552095059a4SDave May   de->communication_status = DEOBJECT_INITIALIZED;
5539566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_DataExchangerPack, 0, 0, 0, 0));
5543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
555095059a4SDave May }
556095059a4SDave May 
5575627991aSBarry Smith /* do the actual message passing */
DMSwarmDataExBegin(DMSwarmDataEx de)558d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExBegin(DMSwarmDataEx de)
559d71ae5a4SJacob Faibussowitsch {
560e91c04dfSPierre Jolivet   PetscMPIInt i, np;
561095059a4SDave May   void       *dest;
562095059a4SDave May 
563095059a4SDave May   PetscFunctionBegin;
56408401ef6SPierre Jolivet   PetscCheck(de->topology_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Topology not finalized");
56508401ef6SPierre Jolivet   PetscCheck(de->message_lengths_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths not finalized");
56608401ef6SPierre Jolivet   PetscCheck(de->packer_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Packer not finalized");
56708401ef6SPierre Jolivet   PetscCheck(de->communication_status != DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Communication has already been finalized. Must call DMSwarmDataExInitialize() first.");
56828b400f6SJacob Faibussowitsch   PetscCheck(de->recv_message, de->comm, PETSC_ERR_ORDER, "recv_message has not been initialized. Must call DMSwarmDataExPackFinalize() first");
5699566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_DataExchangerBegin, 0, 0, 0, 0));
570095059a4SDave May   np = de->n_neighbour_procs;
571095059a4SDave May   /* == NON BLOCKING == */
572521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
573095059a4SDave May     dest = ((char *)de->send_message) + de->unit_message_size * de->message_offsets[i];
574e91c04dfSPierre Jolivet     PetscCallMPI(MPIU_Isend(dest, de->messages_to_be_sent[i] * de->unit_message_size, MPI_CHAR, de->neighbour_procs[i], de->send_tags[i], de->comm, &de->_requests[i]));
575095059a4SDave May   }
5769566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_DataExchangerBegin, 0, 0, 0, 0));
5773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
578095059a4SDave May }
579095059a4SDave May 
580095059a4SDave May /* do the actual message passing now */
DMSwarmDataExEnd(DMSwarmDataEx de)581d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExEnd(DMSwarmDataEx de)
582d71ae5a4SJacob Faibussowitsch {
583e91c04dfSPierre Jolivet   PetscMPIInt i, np;
584095059a4SDave May   PetscInt    total;
585095059a4SDave May   PetscInt   *message_recv_offsets;
586095059a4SDave May   void       *dest;
587095059a4SDave May 
588095059a4SDave May   PetscFunctionBegin;
58908401ef6SPierre Jolivet   PetscCheck(de->communication_status == DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Communication has not been initialized. Must call DMSwarmDataExInitialize() first.");
59028b400f6SJacob Faibussowitsch   PetscCheck(de->recv_message, de->comm, PETSC_ERR_ORDER, "recv_message has not been initialized. Must call DMSwarmDataExPackFinalize() first");
5919566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_DataExchangerEnd, 0, 0, 0, 0));
592095059a4SDave May   np = de->n_neighbour_procs;
5939566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(np + 1, &message_recv_offsets));
594095059a4SDave May   message_recv_offsets[0] = 0;
595095059a4SDave May   total                   = de->messages_to_be_recvieved[0];
596521f74f9SMatthew G. Knepley   for (i = 1; i < np; ++i) {
597095059a4SDave May     message_recv_offsets[i] = total;
598095059a4SDave May     total                   = total + de->messages_to_be_recvieved[i];
599095059a4SDave May   }
600095059a4SDave May   /* == NON BLOCKING == */
601521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
602095059a4SDave May     dest = ((char *)de->recv_message) + de->unit_message_size * message_recv_offsets[i];
603e91c04dfSPierre Jolivet     PetscCallMPI(MPIU_Irecv(dest, de->messages_to_be_recvieved[i] * de->unit_message_size, MPI_CHAR, de->neighbour_procs[i], de->recv_tags[i], de->comm, &de->_requests[np + i]));
604095059a4SDave May   }
6059566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Waitall(2 * np, de->_requests, de->_stats));
6069566063dSJacob Faibussowitsch   PetscCall(PetscFree(message_recv_offsets));
607095059a4SDave May   de->communication_status = DEOBJECT_FINALIZED;
6089566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_DataExchangerEnd, 0, 0, 0, 0));
6093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
610095059a4SDave May }
611095059a4SDave May 
DMSwarmDataExGetSendData(DMSwarmDataEx de,PetscInt * length,void ** send)612d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExGetSendData(DMSwarmDataEx de, PetscInt *length, void **send)
613d71ae5a4SJacob Faibussowitsch {
614095059a4SDave May   PetscFunctionBegin;
61508401ef6SPierre Jolivet   PetscCheck(de->packer_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ARG_WRONGSTATE, "Data has not finished being packed.");
616095059a4SDave May   *length = de->send_message_length;
617095059a4SDave May   *send   = de->send_message;
6183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
619095059a4SDave May }
620095059a4SDave May 
DMSwarmDataExGetRecvData(DMSwarmDataEx de,PetscInt * length,void ** recv)621d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExGetRecvData(DMSwarmDataEx de, PetscInt *length, void **recv)
622d71ae5a4SJacob Faibussowitsch {
623095059a4SDave May   PetscFunctionBegin;
62408401ef6SPierre Jolivet   PetscCheck(de->communication_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ARG_WRONGSTATE, "Data has not finished being sent.");
625095059a4SDave May   *length = de->recv_message_length;
626095059a4SDave May   *recv   = de->recv_message;
6273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
628095059a4SDave May }
629095059a4SDave May 
DMSwarmDataExTopologyGetNeighbours(DMSwarmDataEx de,PetscMPIInt * n,PetscMPIInt * neigh[])630d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExTopologyGetNeighbours(DMSwarmDataEx de, PetscMPIInt *n, PetscMPIInt *neigh[])
631d71ae5a4SJacob Faibussowitsch {
632095059a4SDave May   PetscFunctionBegin;
633ad540459SPierre Jolivet   if (n) *n = de->n_neighbour_procs;
634ad540459SPierre Jolivet   if (neigh) *neigh = de->neighbour_procs;
6353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
636095059a4SDave May }
637