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 8095059a4SDave May these paths we can always uniquely assign message identifers. 9095059a4SDave May 10095059a4SDave May edge 11095059a4SDave May 10 12095059a4SDave May proc ---------> proc 13095059a4SDave May 0 <-------- 1 14095059a4SDave May 11 15095059a4SDave May twin 16095059a4SDave May 17095059a4SDave May Eg: Proc 0 send to proc 1 with message id is 10. To recieve the correct 18095059a4SDave May message, proc 1 looks for the edge connected to proc 0, and then the 19095059a4SDave May messgae 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 36095059a4SDave May User has to unpack message themselves. I can get you the pointer for each i 37095059a4SDave May entry, but you'll have to cast it to the appropriate data type. 38095059a4SDave May 39095059a4SDave May 40095059a4SDave May 41095059a4SDave May 42095059a4SDave May Phase A: Build topology 43095059a4SDave May 44095059a4SDave May Phase B: Define message lengths 45095059a4SDave May 46095059a4SDave May Phase C: Pack data 47095059a4SDave May 48095059a4SDave May Phase D: Send data 49095059a4SDave May 50095059a4SDave May // 51095059a4SDave May DataExCreate() 52095059a4SDave May // A 53095059a4SDave May DataExTopologyInitialize() 54095059a4SDave May DataExTopologyAddNeighbour() 55095059a4SDave May DataExTopologyAddNeighbour() 56095059a4SDave May DataExTopologyFinalize() 57095059a4SDave May // B 58095059a4SDave May DataExZeroAllSendCount() 59095059a4SDave May DataExAddToSendCount() 60095059a4SDave May DataExAddToSendCount() 61095059a4SDave May DataExAddToSendCount() 62095059a4SDave May // C 63095059a4SDave May DataExPackInitialize() 64095059a4SDave May DataExPackData() 65095059a4SDave May DataExPackData() 66095059a4SDave May DataExPackFinalize() 67095059a4SDave May // D 68095059a4SDave May DataExBegin() 69095059a4SDave May // ... perform any calculations ... /// 70095059a4SDave May DataExEnd() 71095059a4SDave May 72095059a4SDave May // Call any getters // 73095059a4SDave May 74095059a4SDave May 75095059a4SDave May */ 76095059a4SDave May 77095059a4SDave May #include <petsc.h> 78095059a4SDave May #include <petscvec.h> 79095059a4SDave May #include <petscmat.h> 80095059a4SDave May 81095059a4SDave May #include "data_ex.h" 82095059a4SDave May 83095059a4SDave May const char *status_names[] = {"initialized", "finalized", "unknown"}; 84095059a4SDave May 85095059a4SDave May PetscLogEvent PTATIN_DataExchangerTopologySetup; 86095059a4SDave May PetscLogEvent PTATIN_DataExchangerBegin; 87095059a4SDave May PetscLogEvent PTATIN_DataExchangerEnd; 88095059a4SDave May 89095059a4SDave May #undef __FUNCT__ 90095059a4SDave May #define __FUNCT__ "DataExCreate" 91*521f74f9SMatthew G. Knepley PetscErrorCode DataExCreate(MPI_Comm comm,const PetscInt count, DataEx *ex) 92095059a4SDave May { 93095059a4SDave May PetscErrorCode ierr; 94*521f74f9SMatthew G. Knepley DataEx d; 95095059a4SDave May 96*521f74f9SMatthew G. Knepley PetscFunctionBegin; 97*521f74f9SMatthew G. Knepley ierr = PetscMalloc(sizeof(struct _p_DataEx), &d);CHKERRQ(ierr); 98*521f74f9SMatthew G. Knepley ierr = PetscMemzero(d, sizeof(struct _p_DataEx));CHKERRQ(ierr); 99*521f74f9SMatthew G. Knepley ierr = MPI_Comm_dup(comm,&d->comm);CHKERRQ(ierr); 100*521f74f9SMatthew G. Knepley ierr = MPI_Comm_rank(d->comm,&d->rank);CHKERRQ(ierr); 101095059a4SDave May 102095059a4SDave May d->instance = count; 103095059a4SDave May 104095059a4SDave May d->topology_status = DEOBJECT_STATE_UNKNOWN; 105095059a4SDave May d->message_lengths_status = DEOBJECT_STATE_UNKNOWN; 106095059a4SDave May d->packer_status = DEOBJECT_STATE_UNKNOWN; 107095059a4SDave May d->communication_status = DEOBJECT_STATE_UNKNOWN; 108095059a4SDave May 109095059a4SDave May d->n_neighbour_procs = -1; 110095059a4SDave May d->neighbour_procs = NULL; 111095059a4SDave May 112095059a4SDave May d->messages_to_be_sent = NULL; 113095059a4SDave May d->message_offsets = NULL; 114095059a4SDave May d->messages_to_be_recvieved = NULL; 115095059a4SDave May 116095059a4SDave May d->unit_message_size = -1; 117095059a4SDave May d->send_message = NULL; 118095059a4SDave May d->send_message_length = -1; 119095059a4SDave May d->recv_message = NULL; 120095059a4SDave May d->recv_message_length = -1; 121095059a4SDave May d->total_pack_cnt = -1; 122095059a4SDave May d->pack_cnt = NULL; 123095059a4SDave May 124095059a4SDave May d->send_tags = NULL; 125095059a4SDave May d->recv_tags = NULL; 126095059a4SDave May 127095059a4SDave May d->_stats = NULL; 128095059a4SDave May d->_requests = NULL; 129*521f74f9SMatthew G. Knepley *ex = d; 130*521f74f9SMatthew G. Knepley PetscFunctionReturn(0); 131095059a4SDave May } 132095059a4SDave May 133095059a4SDave May #undef __FUNCT__ 134095059a4SDave May #define __FUNCT__ "DataExView" 135095059a4SDave May PetscErrorCode DataExView(DataEx d) 136095059a4SDave May { 137095059a4SDave May PetscMPIInt p; 138*521f74f9SMatthew G. Knepley PetscErrorCode ierr; 139095059a4SDave May 140095059a4SDave May PetscFunctionBegin; 141*521f74f9SMatthew G. Knepley ierr = PetscPrintf( PETSC_COMM_WORLD, "DataEx: instance=%D\n",d->instance);CHKERRQ(ierr); 142*521f74f9SMatthew G. Knepley ierr = PetscPrintf( PETSC_COMM_WORLD, " topology status: %s \n", status_names[d->topology_status]);CHKERRQ(ierr); 143*521f74f9SMatthew G. Knepley ierr = PetscPrintf( PETSC_COMM_WORLD, " message lengths status: %s \n", status_names[d->message_lengths_status] );CHKERRQ(ierr); 144*521f74f9SMatthew G. Knepley ierr = PetscPrintf( PETSC_COMM_WORLD, " packer status status: %s \n", status_names[d->packer_status] );CHKERRQ(ierr); 145*521f74f9SMatthew G. Knepley ierr = PetscPrintf( PETSC_COMM_WORLD, " communication status: %s \n", status_names[d->communication_status] );CHKERRQ(ierr); 146095059a4SDave May 147095059a4SDave May if (d->topology_status == DEOBJECT_FINALIZED) { 148*521f74f9SMatthew G. Knepley ierr = PetscPrintf( PETSC_COMM_WORLD, " Topology:\n");CHKERRQ(ierr); 149*521f74f9SMatthew G. Knepley ierr = PetscPrintf( PETSC_COMM_SELF, " [%d] neighbours: %d \n", (int)d->rank, (int)d->n_neighbour_procs );CHKERRQ(ierr); 150095059a4SDave May for (p=0; p<d->n_neighbour_procs; p++) { 151*521f74f9SMatthew G. Knepley ierr = PetscPrintf( PETSC_COMM_SELF, " [%d] neighbour[%D] = %d \n", (int)d->rank, p, (int)d->neighbour_procs[p]);CHKERRQ(ierr); 152095059a4SDave May } 153095059a4SDave May } 154095059a4SDave May if (d->message_lengths_status == DEOBJECT_FINALIZED) { 155*521f74f9SMatthew G. Knepley ierr = PetscPrintf( PETSC_COMM_WORLD, " Message lengths:\n");CHKERRQ(ierr); 156*521f74f9SMatthew G. Knepley ierr = PetscPrintf( PETSC_COMM_SELF, " [%d] atomic size: %ld \n", (int)d->rank, (long int)d->unit_message_size );CHKERRQ(ierr); 157095059a4SDave May for (p=0; p<d->n_neighbour_procs; p++) { 158*521f74f9SMatthew G. Knepley ierr = PetscPrintf( PETSC_COMM_SELF, " [%d] >>>>> ( %D units :: tag = %d ) >>>>> [%d] \n", (int)d->rank, d->messages_to_be_sent[p], d->send_tags[p], (int)d->neighbour_procs[p] );CHKERRQ(ierr); 159095059a4SDave May } 160095059a4SDave May for (p=0; p<d->n_neighbour_procs; p++) { 161*521f74f9SMatthew G. Knepley ierr = PetscPrintf( PETSC_COMM_SELF, " [%d] <<<<< ( %D units :: tag = %d ) <<<<< [%d] \n", (int)d->rank, d->messages_to_be_recvieved[p], d->recv_tags[p], (int)d->neighbour_procs[p] );CHKERRQ(ierr); 162095059a4SDave May } 163095059a4SDave May } 164*521f74f9SMatthew G. Knepley if (d->packer_status == DEOBJECT_FINALIZED) {} 165*521f74f9SMatthew G. Knepley if (d->communication_status == DEOBJECT_FINALIZED) {} 166095059a4SDave May PetscFunctionReturn(0); 167095059a4SDave May } 168095059a4SDave May 169095059a4SDave May #undef __FUNCT__ 170095059a4SDave May #define __FUNCT__ "DataExDestroy" 171095059a4SDave May PetscErrorCode DataExDestroy(DataEx d) 172095059a4SDave May { 173095059a4SDave May PetscErrorCode ierr; 174095059a4SDave May 175095059a4SDave May PetscFunctionBegin; 176095059a4SDave May ierr = MPI_Comm_free(&d->comm);CHKERRQ(ierr); 177*521f74f9SMatthew G. Knepley if (d->neighbour_procs) {ierr = PetscFree(d->neighbour_procs);CHKERRQ(ierr);} 178*521f74f9SMatthew G. Knepley if (d->messages_to_be_sent) {ierr = PetscFree(d->messages_to_be_sent);CHKERRQ(ierr);} 179*521f74f9SMatthew G. Knepley if (d->message_offsets) {ierr = PetscFree(d->message_offsets);CHKERRQ(ierr);} 180*521f74f9SMatthew G. Knepley if (d->messages_to_be_recvieved) {ierr = PetscFree(d->messages_to_be_recvieved);CHKERRQ(ierr);} 181*521f74f9SMatthew G. Knepley if (d->send_message) {ierr = PetscFree(d->send_message);CHKERRQ(ierr);} 182*521f74f9SMatthew G. Knepley if (d->recv_message) {ierr = PetscFree(d->recv_message);CHKERRQ(ierr);} 183*521f74f9SMatthew G. Knepley if (d->pack_cnt) {ierr = PetscFree(d->pack_cnt);CHKERRQ(ierr);} 184*521f74f9SMatthew G. Knepley if (d->send_tags) {ierr = PetscFree(d->send_tags);CHKERRQ(ierr);} 185*521f74f9SMatthew G. Knepley if (d->recv_tags) {ierr = PetscFree(d->recv_tags);CHKERRQ(ierr);} 186*521f74f9SMatthew G. Knepley if (d->_stats) {ierr = PetscFree(d->_stats);CHKERRQ(ierr);} 187*521f74f9SMatthew G. Knepley if (d->_requests) {ierr = PetscFree(d->_requests);CHKERRQ(ierr);} 188*521f74f9SMatthew G. Knepley ierr = PetscFree(d);CHKERRQ(ierr); 189095059a4SDave May PetscFunctionReturn(0); 190095059a4SDave May } 191095059a4SDave May 192095059a4SDave May /* === Phase A === */ 193095059a4SDave May 194095059a4SDave May #undef __FUNCT__ 195095059a4SDave May #define __FUNCT__ "DataExTopologyInitialize" 196095059a4SDave May PetscErrorCode DataExTopologyInitialize(DataEx d) 197095059a4SDave May { 198*521f74f9SMatthew G. Knepley PetscErrorCode ierr; 199*521f74f9SMatthew G. Knepley 200095059a4SDave May PetscFunctionBegin; 201095059a4SDave May d->topology_status = DEOBJECT_INITIALIZED; 202095059a4SDave May d->n_neighbour_procs = 0; 203*521f74f9SMatthew G. Knepley if (d->neighbour_procs ) {ierr = PetscFree(d->neighbour_procs); d->neighbour_procs = NULL;} 204*521f74f9SMatthew G. Knepley if (d->messages_to_be_sent ) {ierr = PetscFree(d->messages_to_be_sent); d->messages_to_be_sent = NULL;} 205*521f74f9SMatthew G. Knepley if (d->message_offsets ) {ierr = PetscFree(d->message_offsets); d->message_offsets = NULL;} 206*521f74f9SMatthew G. Knepley if (d->messages_to_be_recvieved) {ierr = PetscFree(d->messages_to_be_recvieved); d->messages_to_be_recvieved = NULL;} 207*521f74f9SMatthew G. Knepley if (d->pack_cnt ) {ierr = PetscFree(d->pack_cnt); d->pack_cnt = NULL;} 208*521f74f9SMatthew G. Knepley if (d->send_tags) {ierr = PetscFree(d->send_tags); d->send_tags = NULL;} 209*521f74f9SMatthew G. Knepley if (d->recv_tags) {ierr = PetscFree(d->recv_tags); d->recv_tags = NULL;} 210095059a4SDave May PetscFunctionReturn(0); 211095059a4SDave May } 212095059a4SDave May 213095059a4SDave May #undef __FUNCT__ 214095059a4SDave May #define __FUNCT__ "DataExTopologyAddNeighbour" 215095059a4SDave May PetscErrorCode DataExTopologyAddNeighbour(DataEx d,const PetscMPIInt proc_id) 216095059a4SDave May { 217095059a4SDave May PetscMPIInt n,found; 218095059a4SDave May PetscMPIInt nproc; 219095059a4SDave May PetscErrorCode ierr; 220095059a4SDave May 221095059a4SDave May PetscFunctionBegin; 222095059a4SDave May if (d->topology_status == DEOBJECT_FINALIZED) { 223095059a4SDave May SETERRQ(d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology has been finalized. To modify or update call DataExTopologyInitialize() first"); 224*521f74f9SMatthew G. Knepley } else if (d->topology_status != DEOBJECT_INITIALIZED) { 225095059a4SDave May SETERRQ(d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology must be intialised. Call DataExTopologyInitialize() first"); 226095059a4SDave May } 227095059a4SDave May /* error on negative entries */ 228*521f74f9SMatthew G. Knepley if (proc_id < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Trying to set proc neighbour with a rank < 0"); 229095059a4SDave May /* error on ranks larger than number of procs in communicator */ 230095059a4SDave May ierr = MPI_Comm_size(d->comm,&nproc);CHKERRQ(ierr); 231*521f74f9SMatthew G. Knepley if (proc_id >= nproc) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Trying to set proc neighbour with a rank >= nproc"); 232*521f74f9SMatthew G. Knepley if (d->n_neighbour_procs == 0) {ierr = PetscMalloc1(1, &d->neighbour_procs);CHKERRQ(ierr);} 233095059a4SDave May /* check for proc_id */ 234095059a4SDave May found = 0; 235095059a4SDave May for (n = 0; n < d->n_neighbour_procs; n++) { 236095059a4SDave May if (d->neighbour_procs[n] == proc_id) { 237095059a4SDave May found = 1; 238095059a4SDave May } 239095059a4SDave May } 240095059a4SDave May if (found == 0) { /* add it to list */ 241095059a4SDave May PetscMPIInt *tmp; 242095059a4SDave May 243095059a4SDave May tmp = (PetscMPIInt*) realloc(d->neighbour_procs, sizeof(PetscMPIInt)*(d->n_neighbour_procs+1)); 244095059a4SDave May d->neighbour_procs = tmp; 245095059a4SDave May d->neighbour_procs[ d->n_neighbour_procs ] = proc_id; 246095059a4SDave May d->n_neighbour_procs++; 247095059a4SDave May } 248095059a4SDave May PetscFunctionReturn(0); 249095059a4SDave May } 250095059a4SDave May 251095059a4SDave May /* 252095059a4SDave May counter: the index of the communication object 253095059a4SDave May N: the number of processors 254095059a4SDave May r0: rank of sender 255095059a4SDave May r1: rank of receiver 256095059a4SDave May 257095059a4SDave May procs = { 0, 1, 2, 3 } 258095059a4SDave May 259095059a4SDave May 0 ==> 0 e=0 260095059a4SDave May 0 ==> 1 e=1 261095059a4SDave May 0 ==> 2 e=2 262095059a4SDave May 0 ==> 3 e=3 263095059a4SDave May 264095059a4SDave May 1 ==> 0 e=4 265095059a4SDave May 1 ==> 1 e=5 266095059a4SDave May 1 ==> 2 e=6 267095059a4SDave May 1 ==> 3 e=7 268095059a4SDave May 269095059a4SDave May 2 ==> 0 e=8 270095059a4SDave May 2 ==> 1 e=9 271095059a4SDave May 2 ==> 2 e=10 272095059a4SDave May 2 ==> 3 e=11 273095059a4SDave May 274095059a4SDave May 3 ==> 0 e=12 275095059a4SDave May 3 ==> 1 e=13 276095059a4SDave May 3 ==> 2 e=14 277095059a4SDave May 3 ==> 3 e=15 278095059a4SDave May 279095059a4SDave May If we require that proc A sends to proc B, then the SEND tag index will be given by 280095059a4SDave May N * rank(A) + rank(B) + offset 281095059a4SDave May If we require that proc A will receive from proc B, then the RECV tag index will be given by 282095059a4SDave May N * rank(B) + rank(A) + offset 283095059a4SDave May 284095059a4SDave May */ 285*521f74f9SMatthew G. Knepley static void _get_tags(PetscInt counter, PetscMPIInt N, PetscMPIInt r0,PetscMPIInt r1, PetscMPIInt *_st, PetscMPIInt *_rt) 286095059a4SDave May { 287095059a4SDave May PetscMPIInt st,rt; 288095059a4SDave May 289095059a4SDave May st = N*r0 + r1 + N*N*counter; 290095059a4SDave May rt = N*r1 + r0 + N*N*counter; 291095059a4SDave May *_st = st; 292095059a4SDave May *_rt = rt; 293095059a4SDave May } 294095059a4SDave May 295095059a4SDave May /* 296095059a4SDave May Makes the communication map symmetric 297095059a4SDave May */ 298095059a4SDave May #undef __FUNCT__ 299095059a4SDave May #define __FUNCT__ "_DataExCompleteCommunicationMap" 300095059a4SDave May PetscErrorCode _DataExCompleteCommunicationMap(MPI_Comm comm,PetscMPIInt n,PetscMPIInt proc_neighbours[],PetscMPIInt *n_new,PetscMPIInt **proc_neighbours_new) 301095059a4SDave May { 302dcf43ee8SDave May Mat A; 303095059a4SDave May PetscInt i,j,nc; 304095059a4SDave May PetscInt n_, *proc_neighbours_; 305095059a4SDave May PetscInt rank_i_; 306095059a4SDave May PetscMPIInt size, rank_i; 307095059a4SDave May PetscScalar *vals; 308095059a4SDave May const PetscInt *cols; 309095059a4SDave May const PetscScalar *red_vals; 310095059a4SDave May PetscMPIInt _n_new, *_proc_neighbours_new; 311095059a4SDave May PetscErrorCode ierr; 312095059a4SDave May 313095059a4SDave May PetscFunctionBegin; 314095059a4SDave May n_ = n; 315095059a4SDave May ierr = PetscMalloc(sizeof(PetscInt) * n_, &proc_neighbours_);CHKERRQ(ierr); 316*521f74f9SMatthew G. Knepley for (i = 0; i < n_; ++i) { 317095059a4SDave May proc_neighbours_[i] = proc_neighbours[i]; 318095059a4SDave May } 319095059a4SDave May ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 320095059a4SDave May ierr = MPI_Comm_rank(comm,&rank_i);CHKERRQ(ierr); 321095059a4SDave May rank_i_ = rank_i; 322095059a4SDave May 323095059a4SDave May ierr = MatCreate(comm,&A);CHKERRQ(ierr); 324095059a4SDave May ierr = MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,size,size);CHKERRQ(ierr); 325095059a4SDave May ierr = MatSetType(A,MATAIJ);CHKERRQ(ierr); 326dcf43ee8SDave May ierr = MatSeqAIJSetPreallocation(A,1,NULL);CHKERRQ(ierr); 327dcf43ee8SDave May ierr = MatMPIAIJSetPreallocation(A,n_,NULL,n_,NULL);CHKERRQ(ierr); 328dcf43ee8SDave May ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);CHKERRQ(ierr); 329095059a4SDave May /* Build original map */ 330*521f74f9SMatthew G. Knepley ierr = PetscMalloc1(n_, &vals);CHKERRQ(ierr); 331*521f74f9SMatthew G. Knepley for (i = 0; i < n_; ++i) { 332095059a4SDave May vals[i] = 1.0; 333095059a4SDave May } 334095059a4SDave May ierr = MatSetValues( A, 1,&rank_i_, n_,proc_neighbours_, vals, INSERT_VALUES );CHKERRQ(ierr); 335095059a4SDave May ierr = MatAssemblyBegin(A,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr); 336095059a4SDave May ierr = MatAssemblyEnd(A,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr); 337095059a4SDave May /* Now force all other connections if they are not already there */ 338095059a4SDave May /* It's more efficient to do them all at once */ 339*521f74f9SMatthew G. Knepley for (i = 0; i < n_; ++i) { 340095059a4SDave May vals[i] = 2.0; 341095059a4SDave May } 342095059a4SDave May ierr = MatSetValues( A, n_,proc_neighbours_, 1,&rank_i_, vals, INSERT_VALUES );CHKERRQ(ierr); 343095059a4SDave May ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 344095059a4SDave May ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3456275818cSDave May /* 346095059a4SDave May ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD,PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr); 347095059a4SDave May ierr = MatView(A,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 348095059a4SDave May ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3496275818cSDave May */ 350095059a4SDave May if ((n_new != NULL) && (proc_neighbours_new != NULL)) { 351dcf43ee8SDave May ierr = MatGetRow(A, rank_i_, &nc, &cols, &red_vals);CHKERRQ(ierr); 352095059a4SDave May _n_new = (PetscMPIInt) nc; 353*521f74f9SMatthew G. Knepley ierr = PetscMalloc1(_n_new, &_proc_neighbours_new);CHKERRQ(ierr); 354*521f74f9SMatthew G. Knepley for (j = 0; j < nc; ++j) { 355095059a4SDave May _proc_neighbours_new[j] = (PetscMPIInt)cols[j]; 356095059a4SDave May } 357dcf43ee8SDave May ierr = MatRestoreRow( A, rank_i_, &nc, &cols, &red_vals );CHKERRQ(ierr); 358095059a4SDave May *n_new = (PetscMPIInt)_n_new; 359095059a4SDave May *proc_neighbours_new = (PetscMPIInt*)_proc_neighbours_new; 360095059a4SDave May } 361095059a4SDave May ierr = MatDestroy(&A);CHKERRQ(ierr); 362095059a4SDave May ierr = PetscFree(vals);CHKERRQ(ierr); 363095059a4SDave May ierr = PetscFree(proc_neighbours_);CHKERRQ(ierr); 364095059a4SDave May ierr = MPI_Barrier(comm);CHKERRQ(ierr); 365095059a4SDave May PetscFunctionReturn(0); 366095059a4SDave May } 367095059a4SDave May 368095059a4SDave May #undef __FUNCT__ 369095059a4SDave May #define __FUNCT__ "DataExTopologyFinalize" 370095059a4SDave May PetscErrorCode DataExTopologyFinalize(DataEx d) 371095059a4SDave May { 372095059a4SDave May PetscMPIInt symm_nn; 373095059a4SDave May PetscMPIInt *symm_procs; 374095059a4SDave May PetscMPIInt r0,n,st,rt; 375095059a4SDave May PetscMPIInt nprocs; 376095059a4SDave May PetscErrorCode ierr; 377095059a4SDave May 378095059a4SDave May PetscFunctionBegin; 379095059a4SDave May if (d->topology_status != DEOBJECT_INITIALIZED) { 380095059a4SDave May SETERRQ(d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology must be intialised. Call DataExTopologyInitialize() first"); 381095059a4SDave May } 382095059a4SDave May ierr = PetscLogEventBegin(PTATIN_DataExchangerTopologySetup,0,0,0,0);CHKERRQ(ierr); 383095059a4SDave May /* given infomation about all my neighbours, make map symmetric */ 384095059a4SDave May ierr = _DataExCompleteCommunicationMap( d->comm,d->n_neighbour_procs,d->neighbour_procs, &symm_nn, &symm_procs );CHKERRQ(ierr); 385095059a4SDave May /* update my arrays */ 386*521f74f9SMatthew G. Knepley ierr = PetscFree(d->neighbour_procs); 387095059a4SDave May d->n_neighbour_procs = symm_nn; 388095059a4SDave May d->neighbour_procs = symm_procs; 389095059a4SDave May /* allocates memory */ 390*521f74f9SMatthew G. Knepley if (!d->messages_to_be_sent) {ierr = PetscMalloc1(d->n_neighbour_procs, &d->messages_to_be_sent);CHKERRQ(ierr);} 391*521f74f9SMatthew G. Knepley if (!d->message_offsets) {ierr = PetscMalloc1(d->n_neighbour_procs, &d->message_offsets);CHKERRQ(ierr);} 392*521f74f9SMatthew G. Knepley if (!d->messages_to_be_recvieved) {ierr = PetscMalloc1(d->n_neighbour_procs, &d->messages_to_be_recvieved);CHKERRQ(ierr);} 393*521f74f9SMatthew G. Knepley if (!d->pack_cnt) {ierr = PetscMalloc(sizeof(PetscInt) * d->n_neighbour_procs, &d->pack_cnt);CHKERRQ(ierr);} 394*521f74f9SMatthew G. Knepley if (!d->_stats) {ierr = PetscMalloc(sizeof(MPI_Status) * 2*d->n_neighbour_procs, &d->_stats);CHKERRQ(ierr);} 395*521f74f9SMatthew G. Knepley if (!d->_requests) {ierr = PetscMalloc(sizeof(MPI_Request) * 2*d->n_neighbour_procs, &d->_requests);CHKERRQ(ierr);} 396*521f74f9SMatthew G. Knepley if (!d->send_tags) {ierr = PetscMalloc(sizeof(int) * d->n_neighbour_procs, &d->send_tags);CHKERRQ(ierr);} 397*521f74f9SMatthew G. Knepley if (!d->recv_tags) {ierr = PetscMalloc(sizeof(int) * d->n_neighbour_procs, &d->recv_tags);CHKERRQ(ierr);} 398095059a4SDave May /* compute message tags */ 399095059a4SDave May ierr = MPI_Comm_size(d->comm,&nprocs);CHKERRQ(ierr); 400095059a4SDave May r0 = d->rank; 401*521f74f9SMatthew G. Knepley for (n = 0; n < d->n_neighbour_procs; ++n) { 402095059a4SDave May PetscMPIInt r1 = d->neighbour_procs[n]; 403095059a4SDave May 404095059a4SDave May _get_tags( d->instance, nprocs, r0,r1, &st, &rt ); 405095059a4SDave May d->send_tags[n] = (int)st; 406095059a4SDave May d->recv_tags[n] = (int)rt; 407095059a4SDave May } 408095059a4SDave May d->topology_status = DEOBJECT_FINALIZED; 409095059a4SDave May ierr = PetscLogEventEnd(PTATIN_DataExchangerTopologySetup,0,0,0,0);CHKERRQ(ierr); 410095059a4SDave May PetscFunctionReturn(0); 411095059a4SDave May } 412095059a4SDave May 413095059a4SDave May /* === Phase B === */ 414095059a4SDave May #undef __FUNCT__ 415095059a4SDave May #define __FUNCT__ "_DataExConvertProcIdToLocalIndex" 416095059a4SDave May PetscErrorCode _DataExConvertProcIdToLocalIndex(DataEx de,PetscMPIInt proc_id,PetscMPIInt *local) 417095059a4SDave May { 418095059a4SDave May PetscMPIInt i,np; 419095059a4SDave May 420095059a4SDave May PetscFunctionBegin; 421095059a4SDave May np = de->n_neighbour_procs; 422095059a4SDave May *local = -1; 423*521f74f9SMatthew G. Knepley for (i = 0; i < np; ++i) { 424095059a4SDave May if (proc_id == de->neighbour_procs[i]) { 425095059a4SDave May *local = i; 426095059a4SDave May break; 427095059a4SDave May } 428095059a4SDave May } 429095059a4SDave May PetscFunctionReturn(0); 430095059a4SDave May } 431095059a4SDave May 432095059a4SDave May #undef __FUNCT__ 433095059a4SDave May #define __FUNCT__ "DataExInitializeSendCount" 434095059a4SDave May PetscErrorCode DataExInitializeSendCount(DataEx de) 435095059a4SDave May { 436095059a4SDave May PetscMPIInt i; 437095059a4SDave May 438095059a4SDave May PetscFunctionBegin; 439*521f74f9SMatthew G. Knepley if (de->topology_status != DEOBJECT_FINALIZED) SETERRQ(de->comm, PETSC_ERR_ORDER, "Topology not finalized"); 440095059a4SDave May de->message_lengths_status = DEOBJECT_INITIALIZED; 441*521f74f9SMatthew G. Knepley for (i = 0; i < de->n_neighbour_procs; ++i) { 442095059a4SDave May de->messages_to_be_sent[i] = 0; 443095059a4SDave May } 444095059a4SDave May PetscFunctionReturn(0); 445095059a4SDave May } 446095059a4SDave May 447095059a4SDave May /* 448095059a4SDave May 1) only allows counters to be set on neighbouring cpus 449095059a4SDave May */ 450095059a4SDave May #undef __FUNCT__ 451095059a4SDave May #define __FUNCT__ "DataExAddToSendCount" 452095059a4SDave May PetscErrorCode DataExAddToSendCount(DataEx de,const PetscMPIInt proc_id,const PetscInt count) 453095059a4SDave May { 454095059a4SDave May PetscMPIInt local_val; 455095059a4SDave May PetscErrorCode ierr; 456095059a4SDave May 457095059a4SDave May PetscFunctionBegin; 458095059a4SDave May if (de->message_lengths_status == DEOBJECT_FINALIZED) { 459095059a4SDave May SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths have been defined. To modify these call DataExInitializeSendCount() first" ); 460*521f74f9SMatthew G. Knepley } else if (de->message_lengths_status != DEOBJECT_INITIALIZED) { 461095059a4SDave May SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths must be defined. Call DataExInitializeSendCount() first" ); 462095059a4SDave May } 463095059a4SDave May ierr = _DataExConvertProcIdToLocalIndex( de, proc_id, &local_val );CHKERRQ(ierr); 464095059a4SDave May if (local_val == -1) { 465095059a4SDave May SETERRQ1( PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,"Proc %d is not a valid neighbour rank", (int)proc_id ); 466095059a4SDave May } 467095059a4SDave May de->messages_to_be_sent[local_val] = de->messages_to_be_sent[local_val] + count; 468095059a4SDave May PetscFunctionReturn(0); 469095059a4SDave May } 470095059a4SDave May 471095059a4SDave May #undef __FUNCT__ 472095059a4SDave May #define __FUNCT__ "DataExFinalizeSendCount" 473095059a4SDave May PetscErrorCode DataExFinalizeSendCount(DataEx de) 474095059a4SDave May { 475095059a4SDave May PetscFunctionBegin; 476095059a4SDave May if (de->message_lengths_status != DEOBJECT_INITIALIZED) { 477095059a4SDave May SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths must be defined. Call DataExInitializeSendCount() first" ); 478095059a4SDave May } 479095059a4SDave May de->message_lengths_status = DEOBJECT_FINALIZED; 480095059a4SDave May PetscFunctionReturn(0); 481095059a4SDave May } 482095059a4SDave May 483095059a4SDave May /* === Phase C === */ 484095059a4SDave May /* 485095059a4SDave May * zero out all send counts 486095059a4SDave May * free send and recv buffers 487095059a4SDave May * zeros out message length 488095059a4SDave May * zeros out all counters 489095059a4SDave May * zero out packed data counters 490095059a4SDave May */ 491095059a4SDave May #undef __FUNCT__ 492095059a4SDave May #define __FUNCT__ "_DataExInitializeTmpStorage" 493095059a4SDave May PetscErrorCode _DataExInitializeTmpStorage(DataEx de) 494095059a4SDave May { 495095059a4SDave May PetscMPIInt i, np; 496*521f74f9SMatthew G. Knepley PetscErrorCode ierr; 497095059a4SDave May 498095059a4SDave May PetscFunctionBegin; 499095059a4SDave May if (de->n_neighbour_procs < 0) { 500095059a4SDave May SETERRQ( PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of neighbour procs < 0"); 501095059a4SDave May } 502*521f74f9SMatthew G. Knepley if (!de->neighbour_procs) { 503095059a4SDave May SETERRQ( PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Neighbour proc list is NULL" ); 504095059a4SDave May } 505095059a4SDave May np = de->n_neighbour_procs; 506*521f74f9SMatthew G. Knepley for (i = 0; i < np; ++i) { 507095059a4SDave May /* de->messages_to_be_sent[i] = -1; */ 508095059a4SDave May de->messages_to_be_recvieved[i] = -1; 509095059a4SDave May } 510*521f74f9SMatthew G. Knepley ierr = PetscFree(de->send_message);CHKERRQ(ierr); 511*521f74f9SMatthew G. Knepley ierr = PetscFree(de->recv_message);CHKERRQ(ierr); 512095059a4SDave May PetscFunctionReturn(0); 513095059a4SDave May } 514095059a4SDave May 515095059a4SDave May /* 516095059a4SDave May *) Zeros out pack data counters 517095059a4SDave May *) Ensures mesaage length is set 518095059a4SDave May *) Checks send counts properly initialized 519095059a4SDave May *) allocates space for pack data 520095059a4SDave May */ 521095059a4SDave May #undef __FUNCT__ 522095059a4SDave May #define __FUNCT__ "DataExPackInitialize" 523095059a4SDave May PetscErrorCode DataExPackInitialize(DataEx de,size_t unit_message_size) 524095059a4SDave May { 525095059a4SDave May PetscMPIInt i,np; 526095059a4SDave May PetscInt total; 527095059a4SDave May PetscErrorCode ierr; 528095059a4SDave May 529095059a4SDave May PetscFunctionBegin; 530*521f74f9SMatthew G. Knepley if (de->topology_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Topology not finalized" ); 531*521f74f9SMatthew G. Knepley if (de->message_lengths_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths not finalized" ); 532095059a4SDave May de->packer_status = DEOBJECT_INITIALIZED; 533095059a4SDave May ierr = _DataExInitializeTmpStorage(de);CHKERRQ(ierr); 534095059a4SDave May np = de->n_neighbour_procs; 535095059a4SDave May de->unit_message_size = unit_message_size; 536095059a4SDave May total = 0; 537*521f74f9SMatthew G. Knepley for (i = 0; i < np; ++i) { 538095059a4SDave May if (de->messages_to_be_sent[i] == -1) { 539095059a4SDave May PetscMPIInt proc_neighour = de->neighbour_procs[i]; 540095059a4SDave May SETERRQ1( PETSC_COMM_SELF, PETSC_ERR_ORDER, "Messages_to_be_sent[neighbour_proc=%d] is un-initialised. Call DataExSetSendCount() first", (int)proc_neighour ); 541095059a4SDave May } 542095059a4SDave May total = total + de->messages_to_be_sent[i]; 543095059a4SDave May } 544095059a4SDave May /* create space for the data to be sent */ 545*521f74f9SMatthew G. Knepley ierr = PetscMalloc(unit_message_size * (total + 1), &de->send_message);CHKERRQ(ierr); 546095059a4SDave May /* initialize memory */ 547*521f74f9SMatthew G. Knepley ierr = PetscMemzero(de->send_message, unit_message_size * (total + 1));CHKERRQ(ierr); 548095059a4SDave May /* set total items to send */ 549095059a4SDave May de->send_message_length = total; 550095059a4SDave May de->message_offsets[0] = 0; 551095059a4SDave May total = de->messages_to_be_sent[0]; 552*521f74f9SMatthew G. Knepley for (i = 1; i < np; ++i) { 553095059a4SDave May de->message_offsets[i] = total; 554095059a4SDave May total = total + de->messages_to_be_sent[i]; 555095059a4SDave May } 556095059a4SDave May /* init the packer counters */ 557095059a4SDave May de->total_pack_cnt = 0; 558*521f74f9SMatthew G. Knepley for (i = 0; i < np; ++i) { 559095059a4SDave May de->pack_cnt[i] = 0; 560095059a4SDave May } 561095059a4SDave May PetscFunctionReturn(0); 562095059a4SDave May } 563095059a4SDave May 564095059a4SDave May /* 565095059a4SDave May *) Ensures data gets been packed appropriately and no overlaps occur 566095059a4SDave May */ 567095059a4SDave May #undef __FUNCT__ 568095059a4SDave May #define __FUNCT__ "DataExPackData" 569095059a4SDave May PetscErrorCode DataExPackData(DataEx de,PetscMPIInt proc_id,PetscInt n,void *data) 570095059a4SDave May { 571095059a4SDave May PetscMPIInt local; 572095059a4SDave May PetscInt insert_location; 573095059a4SDave May void *dest; 574095059a4SDave May PetscErrorCode ierr; 575095059a4SDave May 576095059a4SDave May PetscFunctionBegin; 577095059a4SDave May if (de->packer_status == DEOBJECT_FINALIZED) { 578095059a4SDave May SETERRQ( de->comm, PETSC_ERR_ORDER, "Packed data have been defined. To modify these call DataExInitializeSendCount(), DataExAddToSendCount(), DataExPackInitialize() first" ); 579095059a4SDave May } 580095059a4SDave May else if (de->packer_status != DEOBJECT_INITIALIZED) { 581095059a4SDave May SETERRQ( de->comm, PETSC_ERR_ORDER, "Packed data must be defined. Call DataExInitializeSendCount(), DataExAddToSendCount(), DataExPackInitialize() first" ); 582095059a4SDave May } 583*521f74f9SMatthew G. Knepley if (!de->send_message) SETERRQ( de->comm, PETSC_ERR_ORDER, "send_message is not initialized. Call DataExPackInitialize() first" ); 584095059a4SDave May ierr = _DataExConvertProcIdToLocalIndex( de, proc_id, &local );CHKERRQ(ierr); 585*521f74f9SMatthew G. Knepley if (local == -1) SETERRQ1( PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "proc_id %d is not registered neighbour", (int)proc_id ); 586095059a4SDave May if (n+de->pack_cnt[local] > de->messages_to_be_sent[local]) { 587095059a4SDave May SETERRQ3( PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Trying to pack too many entries to be sent to proc %d. Space requested = %D: Attempt to insert %D", 588095059a4SDave May (int)proc_id, de->messages_to_be_sent[local], n+de->pack_cnt[local] ); 589095059a4SDave May /* don't need this - the catch for too many messages will pick this up. Gives us more info though */ 590095059a4SDave May if (de->packer_status == DEOBJECT_FINALIZED) { 591095059a4SDave May SETERRQ( de->comm, PETSC_ERR_ARG_WRONG, "Cannot insert any more data. DataExPackFinalize() has been called." ); 592095059a4SDave May } 593095059a4SDave May } 594095059a4SDave May /* copy memory */ 595095059a4SDave May insert_location = de->message_offsets[local] + de->pack_cnt[local]; 596095059a4SDave May dest = ((char*)de->send_message) + de->unit_message_size*insert_location; 597*521f74f9SMatthew G. Knepley ierr = PetscMemcpy(dest, data, de->unit_message_size * n);CHKERRQ(ierr); 598095059a4SDave May /* increment counter */ 599095059a4SDave May de->pack_cnt[local] = de->pack_cnt[local] + n; 600095059a4SDave May PetscFunctionReturn(0); 601095059a4SDave May } 602095059a4SDave May 603095059a4SDave May /* 604095059a4SDave May *) Ensures all data has been packed 605095059a4SDave May */ 606095059a4SDave May #undef __FUNCT__ 607095059a4SDave May #define __FUNCT__ "DataExPackFinalize" 608095059a4SDave May PetscErrorCode DataExPackFinalize(DataEx de) 609095059a4SDave May { 610095059a4SDave May PetscMPIInt i,np; 611095059a4SDave May PetscInt total; 612095059a4SDave May PetscErrorCode ierr; 613095059a4SDave May 614095059a4SDave May PetscFunctionBegin; 615*521f74f9SMatthew G. Knepley if (de->packer_status != DEOBJECT_INITIALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Packer has not been initialized. Must call DataExPackInitialize() first." ); 616095059a4SDave May np = de->n_neighbour_procs; 617*521f74f9SMatthew G. Knepley for (i = 0; i < np; ++i) { 618095059a4SDave May if (de->pack_cnt[i] != de->messages_to_be_sent[i]) { 619095059a4SDave May SETERRQ3( PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not all messages for neighbour[%d] have been packed. Expected %D : Inserted %D", 620095059a4SDave May (int)de->neighbour_procs[i], de->messages_to_be_sent[i], de->pack_cnt[i] ); 621095059a4SDave May } 622095059a4SDave May } 623095059a4SDave May /* init */ 624*521f74f9SMatthew G. Knepley for (i = 0; i < np; ++i) { 625095059a4SDave May de->messages_to_be_recvieved[i] = -1; 626095059a4SDave May } 627095059a4SDave May /* figure out the recv counts here */ 628*521f74f9SMatthew G. Knepley for (i = 0; i < np; ++i) { 629095059a4SDave May ierr = MPI_Isend(&de->messages_to_be_sent[i], 1, MPIU_INT, de->neighbour_procs[i], de->send_tags[i], de->comm, &de->_requests[i]);CHKERRQ(ierr); 630095059a4SDave May } 631*521f74f9SMatthew G. Knepley for (i = 0; i < np; ++i) { 632095059a4SDave May ierr = MPI_Irecv(&de->messages_to_be_recvieved[i], 1, MPIU_INT, de->neighbour_procs[i], de->recv_tags[i], de->comm, &de->_requests[np+i]);CHKERRQ(ierr); 633095059a4SDave May } 634095059a4SDave May ierr = MPI_Waitall(2*np, de->_requests, de->_stats);CHKERRQ(ierr); 635095059a4SDave May /* create space for the data to be recvieved */ 636095059a4SDave May total = 0; 637*521f74f9SMatthew G. Knepley for (i = 0; i < np; ++i) { 638095059a4SDave May total = total + de->messages_to_be_recvieved[i]; 639095059a4SDave May } 640*521f74f9SMatthew G. Knepley ierr = PetscMalloc(de->unit_message_size * (total + 1), &de->recv_message);CHKERRQ(ierr); 641095059a4SDave May /* initialize memory */ 642*521f74f9SMatthew G. Knepley ierr = PetscMemzero(de->recv_message, de->unit_message_size * (total + 1));CHKERRQ(ierr); 643095059a4SDave May /* set total items to recieve */ 644095059a4SDave May de->recv_message_length = total; 645095059a4SDave May de->packer_status = DEOBJECT_FINALIZED; 646095059a4SDave May de->communication_status = DEOBJECT_INITIALIZED; 647095059a4SDave May PetscFunctionReturn(0); 648095059a4SDave May } 649095059a4SDave May 650095059a4SDave May /* do the actual message passing now */ 651095059a4SDave May #undef __FUNCT__ 652095059a4SDave May #define __FUNCT__ "DataExBegin" 653095059a4SDave May PetscErrorCode DataExBegin(DataEx de) 654095059a4SDave May { 655095059a4SDave May PetscMPIInt i,np; 656095059a4SDave May void *dest; 657095059a4SDave May PetscInt length; 658095059a4SDave May PetscErrorCode ierr; 659095059a4SDave May 660095059a4SDave May PetscFunctionBegin; 661*521f74f9SMatthew G. Knepley if (de->topology_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Topology not finalized" ); 662*521f74f9SMatthew G. Knepley if (de->message_lengths_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths not finalized" ); 663*521f74f9SMatthew G. Knepley if (de->packer_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Packer not finalized" ); 664*521f74f9SMatthew G. Knepley if (de->communication_status == DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Communication has already been finalized. Must call DataExInitialize() first." ); 665*521f74f9SMatthew G. Knepley if (!de->recv_message) SETERRQ( de->comm, PETSC_ERR_ORDER, "recv_message has not been initialized. Must call DataExPackFinalize() first" ); 666095059a4SDave May ierr = PetscLogEventBegin(PTATIN_DataExchangerBegin,0,0,0,0);CHKERRQ(ierr); 667095059a4SDave May np = de->n_neighbour_procs; 668095059a4SDave May /* == NON BLOCKING == */ 669*521f74f9SMatthew G. Knepley for (i = 0; i < np; ++i) { 670095059a4SDave May length = de->messages_to_be_sent[i] * de->unit_message_size; 671095059a4SDave May dest = ((char*)de->send_message) + de->unit_message_size * de->message_offsets[i]; 672095059a4SDave May ierr = MPI_Isend( dest, length, MPI_CHAR, de->neighbour_procs[i], de->send_tags[i], de->comm, &de->_requests[i] );CHKERRQ(ierr); 673095059a4SDave May } 674095059a4SDave May ierr = PetscLogEventEnd(PTATIN_DataExchangerBegin,0,0,0,0);CHKERRQ(ierr); 675095059a4SDave May PetscFunctionReturn(0); 676095059a4SDave May } 677095059a4SDave May 678095059a4SDave May /* do the actual message passing now */ 679095059a4SDave May #undef __FUNCT__ 680095059a4SDave May #define __FUNCT__ "DataExEnd" 681095059a4SDave May PetscErrorCode DataExEnd(DataEx de) 682095059a4SDave May { 683095059a4SDave May PetscMPIInt i,np; 684095059a4SDave May PetscInt total; 685095059a4SDave May PetscInt *message_recv_offsets; 686095059a4SDave May void *dest; 687095059a4SDave May PetscInt length; 688095059a4SDave May PetscErrorCode ierr; 689095059a4SDave May 690095059a4SDave May PetscFunctionBegin; 691*521f74f9SMatthew G. Knepley if (de->communication_status != DEOBJECT_INITIALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Communication has not been initialized. Must call DataExInitialize() first." ); 692*521f74f9SMatthew G. Knepley if (!de->recv_message) SETERRQ( de->comm, PETSC_ERR_ORDER, "recv_message has not been initialized. Must call DataExPackFinalize() first" ); 693095059a4SDave May ierr = PetscLogEventBegin(PTATIN_DataExchangerEnd,0,0,0,0);CHKERRQ(ierr); 694095059a4SDave May np = de->n_neighbour_procs; 695*521f74f9SMatthew G. Knepley ierr = PetscMalloc1(np, &message_recv_offsets);CHKERRQ(ierr); 696095059a4SDave May message_recv_offsets[0] = 0; 697095059a4SDave May total = de->messages_to_be_recvieved[0]; 698*521f74f9SMatthew G. Knepley for (i = 1; i < np; ++i) { 699095059a4SDave May message_recv_offsets[i] = total; 700095059a4SDave May total = total + de->messages_to_be_recvieved[i]; 701095059a4SDave May } 702095059a4SDave May /* == NON BLOCKING == */ 703*521f74f9SMatthew G. Knepley for (i = 0; i < np; ++i) { 704095059a4SDave May length = de->messages_to_be_recvieved[i] * de->unit_message_size; 705095059a4SDave May dest = ((char*)de->recv_message) + de->unit_message_size * message_recv_offsets[i]; 706095059a4SDave May ierr = MPI_Irecv( dest, length, MPI_CHAR, de->neighbour_procs[i], de->recv_tags[i], de->comm, &de->_requests[np+i] );CHKERRQ(ierr); 707095059a4SDave May } 708095059a4SDave May ierr = MPI_Waitall( 2*np, de->_requests, de->_stats );CHKERRQ(ierr); 709*521f74f9SMatthew G. Knepley ierr = PetscFree(message_recv_offsets); 710095059a4SDave May de->communication_status = DEOBJECT_FINALIZED; 711095059a4SDave May ierr = PetscLogEventEnd(PTATIN_DataExchangerEnd,0,0,0,0);CHKERRQ(ierr); 712095059a4SDave May PetscFunctionReturn(0); 713095059a4SDave May } 714095059a4SDave May 715095059a4SDave May #undef __FUNCT__ 716095059a4SDave May #define __FUNCT__ "DataExGetSendData" 717095059a4SDave May PetscErrorCode DataExGetSendData(DataEx de,PetscInt *length,void **send) 718095059a4SDave May { 719095059a4SDave May PetscFunctionBegin; 720*521f74f9SMatthew G. Knepley if (de->packer_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ARG_WRONGSTATE, "Data has not finished being packed." ); 721095059a4SDave May *length = de->send_message_length; 722095059a4SDave May *send = de->send_message; 723095059a4SDave May PetscFunctionReturn(0); 724095059a4SDave May } 725095059a4SDave May 726095059a4SDave May #undef __FUNCT__ 727095059a4SDave May #define __FUNCT__ "DataExGetRecvData" 728095059a4SDave May PetscErrorCode DataExGetRecvData(DataEx de,PetscInt *length,void **recv) 729095059a4SDave May { 730095059a4SDave May PetscFunctionBegin; 731*521f74f9SMatthew G. Knepley if (de->communication_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ARG_WRONGSTATE, "Data has not finished being sent." ); 732095059a4SDave May *length = de->recv_message_length; 733095059a4SDave May *recv = de->recv_message; 734095059a4SDave May PetscFunctionReturn(0); 735095059a4SDave May } 736095059a4SDave May 737095059a4SDave May #undef __FUNCT__ 738095059a4SDave May #define __FUNCT__ "DataExTopologyGetNeighbours" 739095059a4SDave May PetscErrorCode DataExTopologyGetNeighbours(DataEx de,PetscMPIInt *n,PetscMPIInt *neigh[]) 740095059a4SDave May { 741095059a4SDave May PetscFunctionBegin; 742095059a4SDave May if (n) {*n = de->n_neighbour_procs;} 743095059a4SDave May if (neigh) {*neigh = de->neighbour_procs;} 744095059a4SDave May PetscFunctionReturn(0); 745095059a4SDave May } 746095059a4SDave May 747