1 /*$Id: isltog.c,v 1.58 2000/09/28 21:10:07 bsmith Exp bsmith $*/ 2 3 #include "petscsys.h" /*I "petscsys.h" I*/ 4 #include "src/vec/is/isimpl.h" /*I "petscis.h" I*/ 5 6 #undef __FUNC__ 7 #define __FUNC__ /*<a name="ISLocalToGlobalMappingGetSize"></a>*/"ISLocalToGlobalMappingGetSize" 8 /*@C 9 ISLocalToGlobalMappingGetSize - Gets the local size of a local to global mapping. 10 11 Not Collective 12 13 Input Parameter: 14 . ltog - local to global mapping 15 16 Output Parameter: 17 . n - the number of entries in the local mapping 18 19 Level: advanced 20 21 Concepts: mapping^local to global 22 23 .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate() 24 @*/ 25 int ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping mapping,int *n) 26 { 27 PetscFunctionBegin; 28 PetscValidHeaderSpecific(mapping,IS_LTOGM_COOKIE); 29 *n = mapping->n; 30 PetscFunctionReturn(0); 31 } 32 33 #undef __FUNC__ 34 #define __FUNC__ /*<a name=""></a>*/"ISLocalToGlobalMappingView" 35 /*@C 36 ISLocalToGlobalMappingView - View a local to global mapping 37 38 Not Collective 39 40 Input Parameters: 41 + ltog - local to global mapping 42 - viewer - viewer 43 44 Level: advanced 45 46 Concepts: mapping^local to global 47 48 .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate() 49 @*/ 50 int ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping,Viewer viewer) 51 { 52 int i,ierr,rank; 53 PetscTruth isascii; 54 55 PetscFunctionBegin; 56 PetscValidHeaderSpecific(mapping,IS_LTOGM_COOKIE); 57 if (!viewer) viewer = VIEWER_STDOUT_(mapping->comm); 58 PetscValidHeaderSpecific(viewer,VIEWER_COOKIE); 59 PetscCheckSameComm(mapping,viewer); 60 61 ierr = MPI_Comm_rank(mapping->comm,&rank);CHKERRQ(ierr); 62 ierr = PetscTypeCompare((PetscObject)viewer,ASCII_VIEWER,&isascii);CHKERRQ(ierr); 63 if (isascii) { 64 for (i=0; i<mapping->n; i++) { 65 ierr = ViewerASCIISynchronizedPrintf(viewer,"[%d] %d %d\n",rank,i,mapping->indices[i]);CHKERRQ(ierr); 66 } 67 ierr = ViewerFlush(viewer);CHKERRQ(ierr); 68 } else { 69 SETERRQ1(1,"Viewer type %s not supported for ISLocalToGlobalMapping",((PetscObject)viewer)->type_name); 70 } 71 72 PetscFunctionReturn(0); 73 } 74 75 #undef __FUNC__ 76 #define __FUNC__ /*<a name=""></a>*/"ISLocalToGlobalMappingCreateIS" 77 /*@C 78 ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n) 79 ordering and a global parallel ordering. 80 81 Not collective 82 83 Input Parameter: 84 . is - index set containing the global numbers for each local 85 86 Output Parameter: 87 . mapping - new mapping data structure 88 89 Level: advanced 90 91 Concepts: mapping^local to global 92 93 .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreate() 94 @*/ 95 int ISLocalToGlobalMappingCreateIS(IS is,ISLocalToGlobalMapping *mapping) 96 { 97 int n,*indices,ierr; 98 MPI_Comm comm; 99 100 PetscFunctionBegin; 101 PetscValidHeaderSpecific(is,IS_COOKIE); 102 103 ierr = PetscObjectGetComm((PetscObject)is,&comm);CHKERRQ(ierr); 104 ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr); 105 ierr = ISGetIndices(is,&indices);CHKERRQ(ierr); 106 ierr = ISLocalToGlobalMappingCreate(comm,n,indices,mapping);CHKERRQ(ierr); 107 ierr = ISRestoreIndices(is,&indices);CHKERRQ(ierr); 108 109 PetscFunctionReturn(0); 110 } 111 112 #undef __FUNC__ 113 #define __FUNC__ /*<a name=""></a>*/"ISLocalToGlobalMappingCreate" 114 /*@C 115 ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n) 116 ordering and a global parallel ordering. 117 118 Not Collective, but communicator may have more than one process 119 120 Input Parameters: 121 + comm - MPI communicator 122 . n - the number of local elements 123 - indices - the global index for each local element 124 125 Output Parameter: 126 . mapping - new mapping data structure 127 128 Level: advanced 129 130 Concepts: mapping^local to global 131 132 .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS() 133 @*/ 134 int ISLocalToGlobalMappingCreate(MPI_Comm cm,int n,const int indices[],ISLocalToGlobalMapping *mapping) 135 { 136 int ierr; 137 138 PetscFunctionBegin; 139 PetscValidIntPointer(indices); 140 PetscValidPointer(mapping); 141 142 PetscHeaderCreate(*mapping,_p_ISLocalToGlobalMapping,int,IS_LTOGM_COOKIE,0,"ISLocalToGlobalMapping", 143 cm,ISLocalToGlobalMappingDestroy,ISLocalToGlobalMappingView); 144 PLogObjectCreate(*mapping); 145 PLogObjectMemory(*mapping,sizeof(struct _p_ISLocalToGlobalMapping)+n*sizeof(int)); 146 147 (*mapping)->n = n; 148 (*mapping)->indices = (int*)PetscMalloc((n+1)*sizeof(int));CHKPTRQ((*mapping)->indices); 149 ierr = PetscMemcpy((*mapping)->indices,indices,n*sizeof(int));CHKERRQ(ierr); 150 151 /* 152 Do not create the global to local mapping. This is only created if 153 ISGlobalToLocalMapping() is called 154 */ 155 (*mapping)->globals = 0; 156 PetscFunctionReturn(0); 157 } 158 159 #undef __FUNC__ 160 #define __FUNC__ /*<a name=""></a>*/"ISLocalToGlobalMappingDestroy" 161 /*@ 162 ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n) 163 ordering and a global parallel ordering. 164 165 Note Collective 166 167 Input Parameters: 168 . mapping - mapping data structure 169 170 Level: advanced 171 172 .seealso: ISLocalToGlobalMappingCreate() 173 @*/ 174 int ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping mapping) 175 { 176 int ierr; 177 PetscFunctionBegin; 178 PetscValidPointer(mapping); 179 if (--mapping->refct > 0) PetscFunctionReturn(0); 180 if (mapping->refct < 0) { 181 SETERRQ(1,"Mapping already destroyed"); 182 } 183 184 ierr = PetscFree(mapping->indices);CHKERRQ(ierr); 185 if (mapping->globals) {ierr = PetscFree(mapping->globals);CHKERRQ(ierr);} 186 PLogObjectDestroy(mapping); 187 PetscHeaderDestroy(mapping); 188 PetscFunctionReturn(0); 189 } 190 191 #undef __FUNC__ 192 #define __FUNC__ /*<a name=""></a>*/"ISLocalToGlobalMappingApplyIS" 193 /*@ 194 ISLocalToGlobalMappingApplyIS - Creates from an IS in the local numbering 195 a new index set using the global numbering defined in an ISLocalToGlobalMapping 196 context. 197 198 Not collective 199 200 Input Parameters: 201 + mapping - mapping between local and global numbering 202 - is - index set in local numbering 203 204 Output Parameters: 205 . newis - index set in global numbering 206 207 Level: advanced 208 209 Concepts: mapping^local to global 210 211 .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(), 212 ISLocalToGlobalMappingDestroy(), ISGlobalToLocalMappingApply() 213 @*/ 214 int ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping,IS is,IS *newis) 215 { 216 int ierr,n,i,*idxin,*idxmap,*idxout,Nmax = mapping->n; 217 218 PetscFunctionBegin; 219 PetscValidPointer(mapping); 220 PetscValidHeaderSpecific(is,IS_COOKIE); 221 PetscValidPointer(newis); 222 223 ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr); 224 ierr = ISGetIndices(is,&idxin);CHKERRQ(ierr); 225 idxmap = mapping->indices; 226 227 idxout = (int*)PetscMalloc((n+1)*sizeof(int));CHKPTRQ(idxout); 228 for (i=0; i<n; i++) { 229 if (idxin[i] >= Nmax) SETERRQ3(PETSC_ERR_ARG_OUTOFRANGE,"Local index %d too large %d (max) at %d",idxin[i],Nmax,i); 230 idxout[i] = idxmap[idxin[i]]; 231 } 232 ierr = ISRestoreIndices(is,&idxin);CHKERRQ(ierr); 233 ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idxout,newis);CHKERRQ(ierr); 234 ierr = PetscFree(idxout);CHKERRQ(ierr); 235 PetscFunctionReturn(0); 236 } 237 238 /*MC 239 ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering 240 and converts them to the global numbering. 241 242 Not collective 243 244 Input Parameters: 245 + mapping - the local to global mapping context 246 . N - number of integers 247 - in - input indices in local numbering 248 249 Output Parameter: 250 . out - indices in global numbering 251 252 Synopsis: 253 ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping,int N,int in[],int out[]) 254 255 Notes: 256 The in and out array parameters may be identical. 257 258 Level: advanced 259 260 .seealso: ISLocalToGlobalMappingCreate(),ISLocalToGlobalMappingDestroy(), 261 ISLocalToGlobalMappingApplyIS(),AOCreateBasic(),AOApplicationToPetsc(), 262 AOPetscToApplication(), ISGlobalToLocalMappingApply() 263 264 Concepts: mapping^local to global 265 266 M*/ 267 268 /* -----------------------------------------------------------------------------------------*/ 269 270 #undef __FUNC__ 271 #define __FUNC__ /*<a name=""></a>*/"ISGlobalToLocalMappingSetUp_Private" 272 /* 273 Creates the global fields in the ISLocalToGlobalMapping structure 274 */ 275 static int ISGlobalToLocalMappingSetUp_Private(ISLocalToGlobalMapping mapping) 276 { 277 int i,*idx = mapping->indices,n = mapping->n,end,start,*globals; 278 279 PetscFunctionBegin; 280 end = 0; 281 start = 100000000; 282 283 for (i=0; i<n; i++) { 284 if (idx[i] < 0) continue; 285 if (idx[i] < start) start = idx[i]; 286 if (idx[i] > end) end = idx[i]; 287 } 288 if (start > end) {start = 0; end = -1;} 289 mapping->globalstart = start; 290 mapping->globalend = end; 291 292 globals = mapping->globals = (int*)PetscMalloc((end-start+2)*sizeof(int));CHKPTRQ(mapping->globals); 293 for (i=0; i<end-start+1; i++) { 294 globals[i] = -1; 295 } 296 for (i=0; i<n; i++) { 297 if (idx[i] < 0) continue; 298 globals[idx[i] - start] = i; 299 } 300 301 PLogObjectMemory(mapping,(end-start+1)*sizeof(int)); 302 PetscFunctionReturn(0); 303 } 304 305 #undef __FUNC__ 306 #define __FUNC__ /*<a name=""></a>*/"ISGlobalToLocalMappingApply" 307 /*@ 308 ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers 309 specified with a global numbering. 310 311 Not collective 312 313 Input Parameters: 314 + mapping - mapping between local and global numbering 315 . type - IS_GTOLM_MASK - replaces global indices with no local value with -1 316 IS_GTOLM_DROP - drops the indices with no local value from the output list 317 . n - number of global indices to map 318 - idx - global indices to map 319 320 Output Parameters: 321 + nout - number of indices in output array (if type == IS_GTOLM_MASK then nout = n) 322 - idxout - local index of each global index, one must pass in an array long enough 323 to hold all the indices. You can call ISGlobalToLocalMappingApply() with 324 idxout == PETSC_NULL to determine the required length (returned in nout) 325 and then allocate the required space and call ISGlobalToLocalMappingApply() 326 a second time to set the values. 327 328 Notes: 329 Either nout or idxout may be PETSC_NULL. idx and idxout may be identical. 330 331 This is not scalable in memory usage. Each processor requires O(Nglobal) size 332 array to compute these. 333 334 Level: advanced 335 336 Concepts: mapping^global to local 337 338 .seealso: ISLocalToGlobalMappingApply(), ISLocalToGlobalMappingCreate(), 339 ISLocalToGlobalMappingDestroy() 340 @*/ 341 int ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping,ISGlobalToLocalMappingType type, 342 int n,const int idx[],int *nout,int idxout[]) 343 { 344 int i,ierr,*globals,nf = 0,tmp,start,end; 345 346 PetscFunctionBegin; 347 if (!mapping->globals) { 348 ierr = ISGlobalToLocalMappingSetUp_Private(mapping);CHKERRQ(ierr); 349 } 350 globals = mapping->globals; 351 start = mapping->globalstart; 352 end = mapping->globalend; 353 354 if (type == IS_GTOLM_MASK) { 355 if (idxout) { 356 for (i=0; i<n; i++) { 357 if (idx[i] < 0) idxout[i] = idx[i]; 358 else if (idx[i] < start) idxout[i] = -1; 359 else if (idx[i] > end) idxout[i] = -1; 360 else idxout[i] = globals[idx[i] - start]; 361 } 362 } 363 if (nout) *nout = n; 364 } else { 365 if (idxout) { 366 for (i=0; i<n; i++) { 367 if (idx[i] < 0) continue; 368 if (idx[i] < start) continue; 369 if (idx[i] > end) continue; 370 tmp = globals[idx[i] - start]; 371 if (tmp < 0) continue; 372 idxout[nf++] = tmp; 373 } 374 } else { 375 for (i=0; i<n; i++) { 376 if (idx[i] < 0) continue; 377 if (idx[i] < start) continue; 378 if (idx[i] > end) continue; 379 tmp = globals[idx[i] - start]; 380 if (tmp < 0) continue; 381 nf++; 382 } 383 } 384 if (nout) *nout = nf; 385 } 386 387 PetscFunctionReturn(0); 388 } 389 390 #undef __FUNC__ 391 #define __FUNC__ /*<a name=""></a>*/"ISLocalToGlobalMappingGetInfo" 392 /*@C 393 ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each processor and 394 each index shared by more than one processor 395 396 Collective on ISLocalToGlobalMapping 397 398 Input Parameters: 399 . mapping - the mapping from local to global indexing 400 401 Output Parameter: 402 + nproc - number of processors that are connected to this one 403 . proc - neighboring processors 404 . numproc - number of indices for each subdomain (processor) 405 - indices - indices of local nodes shared with neighbor (sorted by global numbering) 406 407 Level: advanced 408 409 Concepts: mapping^local to global 410 411 .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(), 412 ISLocalToGlobalMappingRestoreInfo() 413 @*/ 414 int ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping,int *nproc,int **procs,int **numprocs,int ***indices) 415 { 416 int i,n = mapping->n,ierr,Ng,ng = PETSC_DECIDE,max = 0,*lindices = mapping->indices; 417 int size,rank,*nprocs,*owner,nsends,*sends,j,*starts,*work,nmax,nrecvs,*recvs,proc; 418 int tag1,tag2,tag3,cnt,*len,*source,imdex,scale,*ownedsenders,*nownedsenders,rstart,nowned; 419 int node,nownedm,nt,*sends2,nsends2,*starts2,*lens2,*dest,nrecvs2,*starts3,*recvs2,k,*bprocs,*tmp; 420 int first_procs,first_numprocs,*first_indices; 421 MPI_Request *recv_waits,*send_waits; 422 MPI_Status recv_status,*send_status,*recv_statuses; 423 MPI_Comm comm = mapping->comm; 424 PetscTruth debug = PETSC_FALSE; 425 426 PetscFunctionBegin; 427 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 428 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 429 if (size == 1) { 430 *nproc = 0; 431 *procs = PETSC_NULL; 432 *numprocs = (int*)PetscMalloc(sizeof(int));CHKPTRQ(*numprocs); 433 (*numprocs)[0] = 0; 434 *indices = (int**)PetscMalloc(sizeof(int*));CHKPTRQ(*indices); 435 (*indices)[0] = PETSC_NULL; 436 PetscFunctionReturn(0); 437 } 438 439 ierr = OptionsHasName(PETSC_NULL,"-islocaltoglobalmappinggetinfo_debug",&debug);CHKERRQ(ierr); 440 441 /* 442 Notes on ISLocalToGlobalMappingGetInfo 443 444 globally owned node - the nodes that have been assigned to this processor in global 445 numbering, just for this routine. 446 447 nontrivial globally owned node - node assigned to this processor that is on a subdomain 448 boundary (i.e. is has more than one local owner) 449 450 locally owned node - node that exists on this processors subdomain 451 452 nontrivial locally owned node - node that is not in the interior (i.e. has more than one 453 local subdomain 454 */ 455 ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag1);CHKERRQ(ierr); 456 ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag2);CHKERRQ(ierr); 457 ierr = PetscObjectGetNewTag((PetscObject)mapping,&tag3);CHKERRQ(ierr); 458 459 for (i=0; i<n; i++) { 460 if (lindices[i] > max) max = lindices[i]; 461 } 462 ierr = MPI_Allreduce(&max,&Ng,1,MPI_INT,MPI_MAX,comm);CHKERRQ(ierr); 463 Ng++; 464 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 465 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 466 scale = Ng/size + 1; 467 ng = scale; if (rank == size-1) ng = Ng - scale*(size-1); ng = PetscMax(1,ng); 468 rstart = scale*rank; 469 470 /* determine ownership ranges of global indices */ 471 nprocs = (int*)PetscMalloc((2*size+1)*sizeof(int));CHKPTRQ(nprocs); 472 ierr = PetscMemzero(nprocs,2*size*sizeof(int));CHKERRQ(ierr); 473 474 /* determine owners of each local node */ 475 owner = (int*)PetscMalloc((n+1)*sizeof(int));CHKPTRQ(owner); 476 for (i=0; i<n; i++) { 477 proc = lindices[i]/scale; /* processor that globally owns this index */ 478 nprocs[size+proc] = 1; /* processor globally owns at least one of ours */ 479 owner[i] = proc; 480 nprocs[proc]++; /* count of how many that processor globally owns of ours */ 481 } 482 nsends = 0; for (i=0; i<size; i++) nsends += nprocs[size + i]; 483 PLogInfo(0,"ISLocalToGlobalMappingGetInfo: Number of global owners for my local data %d\n",nsends); 484 485 /* inform other processors of number of messages and max length*/ 486 work = (int*)PetscMalloc(2*size*sizeof(int));CHKPTRQ(work); 487 ierr = MPI_Allreduce(nprocs,work,2*size,MPI_INT,PetscMaxSum_Op,comm);CHKERRQ(ierr); 488 nmax = work[rank]; 489 nrecvs = work[size+rank]; 490 ierr = PetscFree(work);CHKERRQ(ierr); 491 PLogInfo(0,"ISLocalToGlobalMappingGetInfo: Number of local owners for my global data %d\n",nrecvs); 492 493 /* post receives for owned rows */ 494 recvs = (int*)PetscMalloc((2*nrecvs+1)*(nmax+1)*sizeof(int));CHKPTRQ(recvs); 495 recv_waits = (MPI_Request*)PetscMalloc((nrecvs+1)*sizeof(MPI_Request));CHKPTRQ(recv_waits); 496 for (i=0; i<nrecvs; i++) { 497 ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPI_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRQ(ierr); 498 } 499 500 /* pack messages containing lists of local nodes to owners */ 501 sends = (int*)PetscMalloc((2*n+1)*sizeof(int));CHKPTRQ(sends); 502 starts = (int*)PetscMalloc((size+1)*sizeof(int));CHKPTRQ(starts); 503 starts[0] = 0; 504 for (i=1; i<size; i++) { starts[i] = starts[i-1] + 2*nprocs[i-1];} 505 for (i=0; i<n; i++) { 506 sends[starts[owner[i]]++] = lindices[i]; 507 sends[starts[owner[i]]++] = i; 508 } 509 ierr = PetscFree(owner);CHKERRQ(ierr); 510 starts[0] = 0; 511 for (i=1; i<size; i++) { starts[i] = starts[i-1] + 2*nprocs[i-1];} 512 513 /* send the messages */ 514 send_waits = (MPI_Request*)PetscMalloc((nsends+1)*sizeof(MPI_Request));CHKPTRQ(send_waits); 515 dest = (int*)PetscMalloc((nsends+1)*sizeof(int));CHKPTRQ(dest); 516 cnt = 0; 517 for (i=0; i<size; i++) { 518 if (nprocs[i]) { 519 ierr = MPI_Isend(sends+starts[i],2*nprocs[i],MPI_INT,i,tag1,comm,send_waits+cnt);CHKERRQ(ierr); 520 dest[cnt] = i; 521 cnt++; 522 } 523 } 524 ierr = PetscFree(starts);CHKERRQ(ierr); 525 526 /* wait on receives */ 527 source = (int*)PetscMalloc((2*nrecvs+1)*sizeof(int));CHKPTRQ(source); 528 len = source + nrecvs; 529 cnt = nrecvs; 530 nownedsenders = (int*)PetscMalloc((ng+1)*sizeof(int));CHKPTRQ(nownedsenders); 531 ierr = PetscMemzero(nownedsenders,ng*sizeof(int));CHKERRQ(ierr); 532 while (cnt) { 533 ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr); 534 /* unpack receives into our local space */ 535 ierr = MPI_Get_count(&recv_status,MPI_INT,&len[imdex]);CHKERRQ(ierr); 536 source[imdex] = recv_status.MPI_SOURCE; 537 len[imdex] = len[imdex]/2; 538 /* count how many local owners for each of my global owned indices */ 539 for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++; 540 cnt--; 541 } 542 ierr = PetscFree(recv_waits);CHKERRQ(ierr); 543 544 /* count how many globally owned indices are on an edge multiplied by how many processors own them. */ 545 nowned = 0; 546 nownedm = 0; 547 for (i=0; i<ng; i++) { 548 if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;} 549 } 550 551 /* create single array to contain rank of all local owners of each globally owned index */ 552 ownedsenders = (int*)PetscMalloc((nownedm+1)*sizeof(int));CHKERRQ(ierr); 553 starts = (int*)PetscMalloc((ng+1)*sizeof(int));CHKPTRQ(starts); 554 starts[0] = 0; 555 for (i=1; i<ng; i++) { 556 if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1]; 557 else starts[i] = starts[i-1]; 558 } 559 560 /* for each nontrival globally owned node list all arriving processors */ 561 for (i=0; i<nrecvs; i++) { 562 for (j=0; j<len[i]; j++) { 563 node = recvs[2*i*nmax+2*j]-rstart; 564 if (nownedsenders[node] > 1) { 565 ownedsenders[starts[node]++] = source[i]; 566 } 567 } 568 } 569 570 if (debug) { /* ----------------------------------- */ 571 starts[0] = 0; 572 for (i=1; i<ng; i++) { 573 if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1]; 574 else starts[i] = starts[i-1]; 575 } 576 for (i=0; i<ng; i++) { 577 if (nownedsenders[i] > 1) { 578 ierr = PetscSynchronizedPrintf(comm,"[%d] global node %d local owner processors: ",rank,i+rstart);CHKERRQ(ierr); 579 for (j=0; j<nownedsenders[i]; j++) { 580 ierr = PetscSynchronizedPrintf(comm,"%d ",ownedsenders[starts[i]+j]);CHKERRQ(ierr); 581 } 582 ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr); 583 } 584 } 585 ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr); 586 }/* ----------------------------------- */ 587 588 /* wait on original sends */ 589 if (nsends) { 590 send_status = (MPI_Status*)PetscMalloc(nsends*sizeof(MPI_Status));CHKPTRQ(send_status); 591 ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr); 592 ierr = PetscFree(send_status);CHKERRQ(ierr); 593 } 594 ierr = PetscFree(send_waits);CHKERRQ(ierr); 595 ierr = PetscFree(sends);CHKERRQ(ierr); 596 ierr = PetscFree(nprocs);CHKERRQ(ierr); 597 598 /* pack messages to send back to local owners */ 599 starts[0] = 0; 600 for (i=1; i<ng; i++) { 601 if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1]; 602 else starts[i] = starts[i-1]; 603 } 604 nsends2 = nrecvs; 605 nprocs = (int*)PetscMalloc((nsends2+1)*sizeof(int));CHKPTRQ(nprocs); /* length of each message */ 606 cnt = 0; 607 for (i=0; i<nrecvs; i++) { 608 nprocs[i] = 1; 609 for (j=0; j<len[i]; j++) { 610 node = recvs[2*i*nmax+2*j]-rstart; 611 if (nownedsenders[node] > 1) { 612 nprocs[i] += 2 + nownedsenders[node]; 613 } 614 } 615 } 616 nt = 0; for (i=0; i<nsends2; i++) nt += nprocs[i]; 617 sends2 = (int*)PetscMalloc((nt+1)*sizeof(int));CHKPTRQ(sends2); 618 starts2 = (int*)PetscMalloc((nsends2+1)*sizeof(int));CHKPTRQ(starts2); 619 starts2[0] = 0; for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1]; 620 /* 621 Each message is 1 + nprocs[i] long, and consists of 622 (0) the number of nodes being sent back 623 (1) the local node number, 624 (2) the number of processors sharing it, 625 (3) the processors sharing it 626 */ 627 for (i=0; i<nsends2; i++) { 628 cnt = 1; 629 sends2[starts2[i]] = 0; 630 for (j=0; j<len[i]; j++) { 631 node = recvs[2*i*nmax+2*j]-rstart; 632 if (nownedsenders[node] > 1) { 633 sends2[starts2[i]]++; 634 sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1]; 635 sends2[starts2[i]+cnt++] = nownedsenders[node]; 636 ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(int));CHKERRQ(ierr); 637 cnt += nownedsenders[node]; 638 } 639 } 640 } 641 642 /* send the message lengths */ 643 for (i=0; i<nsends2; i++) { 644 ierr = MPI_Send(&nprocs[i],1,MPI_INT,source[i],tag2,comm);CHKERRQ(ierr); 645 } 646 647 /* receive the message lengths */ 648 nrecvs2 = nsends; 649 lens2 = (int*)PetscMalloc((nrecvs2+1)*sizeof(int));CHKPTRQ(lens2); 650 starts3 = (int*)PetscMalloc((nrecvs2+1)*sizeof(int));CHKPTRQ(starts3); 651 nt = 0; 652 for (i=0; i<nrecvs2; i++) { 653 ierr = MPI_Recv(&lens2[i],1,MPI_INT,dest[i],tag2,comm,&recv_status);CHKERRQ(ierr); 654 nt += lens2[i]; 655 } 656 starts3[0] = 0; 657 for (i=0; i<nrecvs2-1; i++) { 658 starts3[i+1] = starts3[i] + lens2[i]; 659 } 660 recvs2 = (int*)PetscMalloc((nt+1)*sizeof(int));CHKPTRQ(recvs2); 661 recv_waits = (MPI_Request*)PetscMalloc((nrecvs2+1)*sizeof(MPI_Request));CHKPTRQ(recv_waits); 662 for (i=0; i<nrecvs2; i++) { 663 ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPI_INT,dest[i],tag3,comm,recv_waits+i);CHKERRQ(ierr); 664 } 665 666 /* send the messages */ 667 send_waits = (MPI_Request*)PetscMalloc((nsends2+1)*sizeof(MPI_Request));CHKPTRQ(send_waits); 668 for (i=0; i<nsends2; i++) { 669 ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPI_INT,source[i],tag3,comm,send_waits+i);CHKERRQ(ierr); 670 } 671 672 /* wait on receives */ 673 recv_statuses = (MPI_Status*)PetscMalloc((nrecvs2+1)*sizeof(MPI_Status));CHKPTRQ(recv_statuses); 674 ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr); 675 ierr = PetscFree(recv_statuses);CHKERRQ(ierr); 676 ierr = PetscFree(recv_waits);CHKERRQ(ierr); 677 ierr = PetscFree(nprocs);CHKERRQ(ierr); 678 679 if (debug) { /* ----------------------------------- */ 680 cnt = 0; 681 for (i=0; i<nrecvs2; i++) { 682 nt = recvs2[cnt++]; 683 for (j=0; j<nt; j++) { 684 ierr = PetscSynchronizedPrintf(comm,"[%d] local node %d number of subdomains %d: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr); 685 for (k=0; k<recvs2[cnt+1]; k++) { 686 ierr = PetscSynchronizedPrintf(comm,"%d ",recvs2[cnt+2+k]);CHKERRQ(ierr); 687 } 688 cnt += 2 + recvs2[cnt+1]; 689 ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr); 690 } 691 } 692 ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr); 693 } /* ----------------------------------- */ 694 695 /* count number subdomains for each local node */ 696 nprocs = (int*)PetscMalloc(size*sizeof(int));CHKPTRQ(nprocs); 697 ierr = PetscMemzero(nprocs,size*sizeof(int));CHKERRQ(ierr); 698 cnt = 0; 699 for (i=0; i<nrecvs2; i++) { 700 nt = recvs2[cnt++]; 701 for (j=0; j<nt; j++) { 702 for (k=0; k<recvs2[cnt+1]; k++) { 703 nprocs[recvs2[cnt+2+k]]++; 704 } 705 cnt += 2 + recvs2[cnt+1]; 706 } 707 } 708 nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0); 709 *nproc = nt; 710 *procs = (int*)PetscMalloc((nt+1)*sizeof(int));CHKPTRQ(procs); 711 *numprocs = (int*)PetscMalloc((nt+1)*sizeof(int));CHKPTRQ(numprocs); 712 *indices = (int**)PetscMalloc((nt+1)*sizeof(int*));CHKPTRQ(procs); 713 bprocs = (int*)PetscMalloc(size*sizeof(int));CHKERRQ(ierr); 714 cnt = 0; 715 for (i=0; i<size; i++) { 716 if (nprocs[i] > 0) { 717 bprocs[i] = cnt; 718 (*procs)[cnt] = i; 719 (*numprocs)[cnt] = nprocs[i]; 720 (*indices)[cnt] = (int*)PetscMalloc(nprocs[i]*sizeof(int));CHKPTRQ((*indices)[cnt]); 721 cnt++; 722 } 723 } 724 725 /* make the list of subdomains for each nontrivial local node */ 726 ierr = PetscMemzero(*numprocs,nt*sizeof(int));CHKERRQ(ierr); 727 cnt = 0; 728 for (i=0; i<nrecvs2; i++) { 729 nt = recvs2[cnt++]; 730 for (j=0; j<nt; j++) { 731 for (k=0; k<recvs2[cnt+1]; k++) { 732 (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt]; 733 } 734 cnt += 2 + recvs2[cnt+1]; 735 } 736 } 737 ierr = PetscFree(bprocs);CHKERRQ(ierr); 738 ierr = PetscFree(recvs2);CHKERRQ(ierr); 739 740 /* sort the node indexing by their global numbers */ 741 nt = *nproc; 742 for (i=0; i<nt; i++) { 743 tmp = (int*)PetscMalloc(((*numprocs)[i])*sizeof(int));CHKPTRQ(tmp); 744 for (j=0; j<(*numprocs)[i]; j++) { 745 tmp[j] = lindices[(*indices)[i][j]]; 746 } 747 ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr); 748 ierr = PetscFree(tmp);CHKERRQ(ierr); 749 } 750 751 if (debug) { /* ----------------------------------- */ 752 nt = *nproc; 753 for (i=0; i<nt; i++) { 754 ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %d number of indices %d: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr); 755 for (j=0; j<(*numprocs)[i]; j++) { 756 ierr = PetscSynchronizedPrintf(comm,"%d ",(*indices)[i][j]);CHKERRQ(ierr); 757 } 758 ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr); 759 } 760 ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr); 761 } /* ----------------------------------- */ 762 763 /* wait on sends */ 764 if (nsends2) { 765 send_status = (MPI_Status*)PetscMalloc(nsends2*sizeof(MPI_Status));CHKPTRQ(send_status); 766 ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr); 767 ierr = PetscFree(send_status);CHKERRQ(ierr); 768 } 769 770 ierr = PetscFree(starts3);CHKERRQ(ierr); 771 ierr = PetscFree(dest);CHKERRQ(ierr); 772 ierr = PetscFree(send_waits);CHKERRQ(ierr); 773 774 ierr = PetscFree(nownedsenders);CHKERRQ(ierr); 775 ierr = PetscFree(ownedsenders);CHKERRQ(ierr); 776 ierr = PetscFree(starts);CHKERRQ(ierr); 777 ierr = PetscFree(starts2);CHKERRQ(ierr); 778 ierr = PetscFree(lens2);CHKERRQ(ierr); 779 780 ierr = PetscFree(source);CHKERRQ(ierr); 781 ierr = PetscFree(recvs);CHKERRQ(ierr); 782 ierr = PetscFree(nprocs);CHKERRQ(ierr); 783 ierr = PetscFree(sends2);CHKERRQ(ierr); 784 785 /* put the information about myself as the first entry in the list */ 786 first_procs = (*procs)[0]; 787 first_numprocs = (*numprocs)[0]; 788 first_indices = (*indices)[0]; 789 for (i=0; i<*nproc; i++) { 790 if ((*procs)[i] == rank) { 791 (*procs)[0] = (*procs)[i]; 792 (*numprocs)[0] = (*numprocs)[i]; 793 (*indices)[0] = (*indices)[i]; 794 (*procs)[i] = first_procs; 795 (*numprocs)[i] = first_numprocs; 796 (*indices)[i] = first_indices; 797 break; 798 } 799 } 800 801 PetscFunctionReturn(0); 802 } 803 804 #undef __FUNC__ 805 #define __FUNC__ /*<a name=""></a>*/"ISLocalToGlobalMappingRestoreInfo" 806 /*@C 807 ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo() 808 809 Collective on ISLocalToGlobalMapping 810 811 Input Parameters: 812 . mapping - the mapping from local to global indexing 813 814 Output Parameter: 815 + nproc - number of processors that are connected to this one 816 . proc - neighboring processors 817 . numproc - number of indices for each processor 818 - indices - indices of local nodes shared with neighbor (sorted by global numbering) 819 820 Level: advanced 821 822 .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(), 823 ISLocalToGlobalMappingGetInfo() 824 @*/ 825 int ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,int *nproc,int **procs,int **numprocs,int ***indices) 826 { 827 int ierr,i; 828 829 PetscFunctionBegin; 830 if (*procs) {ierr = PetscFree(*procs);CHKERRQ(ierr);} 831 if (*numprocs) {ierr = PetscFree(*numprocs);CHKERRQ(ierr);} 832 if (*indices) { 833 if ((*indices)[0]) {ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);} 834 for (i=1; i<*nproc; i++) { 835 if ((*indices)[i]) {ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);} 836 } 837 ierr = PetscFree(*indices);CHKERRQ(ierr); 838 } 839 PetscFunctionReturn(0); 840 } 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859