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