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