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,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[2*proc+1] = 1; /* processor globally owns at least one of ours */ 564 owner[i] = proc; 565 nprocs[2*proc]++; /* count of how many that processor globally owns of ours */ 566 } 567 nsends = 0; for (i=0; i<size; i++) nsends += nprocs[2*i+1]; 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 = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr); 572 PetscLogInfo(0,"ISLocalToGlobalMappingGetInfo: Number of local owners for my global data %d\n",nrecvs); 573 574 /* post receives for owned rows */ 575 ierr = PetscMalloc((2*nrecvs+1)*(nmax+1)*sizeof(int),&recvs);CHKERRQ(ierr); 576 ierr = PetscMalloc((nrecvs+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr); 577 for (i=0; i<nrecvs; i++) { 578 ierr = MPI_Irecv(recvs+2*nmax*i,2*nmax,MPI_INT,MPI_ANY_SOURCE,tag1,comm,recv_waits+i);CHKERRQ(ierr); 579 } 580 581 /* pack messages containing lists of local nodes to owners */ 582 ierr = PetscMalloc((2*n+1)*sizeof(int),&sends);CHKERRQ(ierr); 583 ierr = PetscMalloc((size+1)*sizeof(int),&starts);CHKERRQ(ierr); 584 starts[0] = 0; 585 for (i=1; i<size; i++) { starts[i] = starts[i-1] + 2*nprocs[2*i-2];} 586 for (i=0; i<n; i++) { 587 sends[starts[owner[i]]++] = lindices[i]; 588 sends[starts[owner[i]]++] = i; 589 } 590 ierr = PetscFree(owner);CHKERRQ(ierr); 591 starts[0] = 0; 592 for (i=1; i<size; i++) { starts[i] = starts[i-1] + 2*nprocs[2*i-2];} 593 594 /* send the messages */ 595 ierr = PetscMalloc((nsends+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr); 596 ierr = PetscMalloc((nsends+1)*sizeof(int),&dest);CHKERRQ(ierr); 597 cnt = 0; 598 for (i=0; i<size; i++) { 599 if (nprocs[2*i]) { 600 ierr = MPI_Isend(sends+starts[i],2*nprocs[2*i],MPI_INT,i,tag1,comm,send_waits+cnt);CHKERRQ(ierr); 601 dest[cnt] = i; 602 cnt++; 603 } 604 } 605 ierr = PetscFree(starts);CHKERRQ(ierr); 606 607 /* wait on receives */ 608 ierr = PetscMalloc((2*nrecvs+1)*sizeof(int),&source);CHKERRQ(ierr); 609 len = source + nrecvs; 610 cnt = nrecvs; 611 ierr = PetscMalloc((ng+1)*sizeof(int),&nownedsenders);CHKERRQ(ierr); 612 ierr = PetscMemzero(nownedsenders,ng*sizeof(int));CHKERRQ(ierr); 613 while (cnt) { 614 ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr); 615 /* unpack receives into our local space */ 616 ierr = MPI_Get_count(&recv_status,MPI_INT,&len[imdex]);CHKERRQ(ierr); 617 source[imdex] = recv_status.MPI_SOURCE; 618 len[imdex] = len[imdex]/2; 619 /* count how many local owners for each of my global owned indices */ 620 for (i=0; i<len[imdex]; i++) nownedsenders[recvs[2*imdex*nmax+2*i]-rstart]++; 621 cnt--; 622 } 623 ierr = PetscFree(recv_waits);CHKERRQ(ierr); 624 625 /* count how many globally owned indices are on an edge multiplied by how many processors own them. */ 626 nowned = 0; 627 nownedm = 0; 628 for (i=0; i<ng; i++) { 629 if (nownedsenders[i] > 1) {nownedm += nownedsenders[i]; nowned++;} 630 } 631 632 /* create single array to contain rank of all local owners of each globally owned index */ 633 ierr = PetscMalloc((nownedm+1)*sizeof(int),&ownedsenders);CHKERRQ(ierr); 634 ierr = PetscMalloc((ng+1)*sizeof(int),&starts);CHKERRQ(ierr); 635 starts[0] = 0; 636 for (i=1; i<ng; i++) { 637 if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1]; 638 else starts[i] = starts[i-1]; 639 } 640 641 /* for each nontrival globally owned node list all arriving processors */ 642 for (i=0; i<nrecvs; i++) { 643 for (j=0; j<len[i]; j++) { 644 node = recvs[2*i*nmax+2*j]-rstart; 645 if (nownedsenders[node] > 1) { 646 ownedsenders[starts[node]++] = source[i]; 647 } 648 } 649 } 650 651 if (debug) { /* ----------------------------------- */ 652 starts[0] = 0; 653 for (i=1; i<ng; i++) { 654 if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1]; 655 else starts[i] = starts[i-1]; 656 } 657 for (i=0; i<ng; i++) { 658 if (nownedsenders[i] > 1) { 659 ierr = PetscSynchronizedPrintf(comm,"[%d] global node %d local owner processors: ",rank,i+rstart);CHKERRQ(ierr); 660 for (j=0; j<nownedsenders[i]; j++) { 661 ierr = PetscSynchronizedPrintf(comm,"%d ",ownedsenders[starts[i]+j]);CHKERRQ(ierr); 662 } 663 ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr); 664 } 665 } 666 ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr); 667 }/* ----------------------------------- */ 668 669 /* wait on original sends */ 670 if (nsends) { 671 ierr = PetscMalloc(nsends*sizeof(MPI_Status),&send_status);CHKERRQ(ierr); 672 ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr); 673 ierr = PetscFree(send_status);CHKERRQ(ierr); 674 } 675 ierr = PetscFree(send_waits);CHKERRQ(ierr); 676 ierr = PetscFree(sends);CHKERRQ(ierr); 677 ierr = PetscFree(nprocs);CHKERRQ(ierr); 678 679 /* pack messages to send back to local owners */ 680 starts[0] = 0; 681 for (i=1; i<ng; i++) { 682 if (nownedsenders[i-1] > 1) starts[i] = starts[i-1] + nownedsenders[i-1]; 683 else starts[i] = starts[i-1]; 684 } 685 nsends2 = nrecvs; 686 ierr = PetscMalloc((nsends2+1)*sizeof(int),&nprocs);CHKERRQ(ierr); /* length of each message */ 687 for (i=0; i<nrecvs; i++) { 688 nprocs[i] = 1; 689 for (j=0; j<len[i]; j++) { 690 node = recvs[2*i*nmax+2*j]-rstart; 691 if (nownedsenders[node] > 1) { 692 nprocs[i] += 2 + nownedsenders[node]; 693 } 694 } 695 } 696 nt = 0; for (i=0; i<nsends2; i++) nt += nprocs[i]; 697 ierr = PetscMalloc((nt+1)*sizeof(int),&sends2);CHKERRQ(ierr); 698 ierr = PetscMalloc((nsends2+1)*sizeof(int),&starts2);CHKERRQ(ierr); 699 starts2[0] = 0; for (i=1; i<nsends2; i++) starts2[i] = starts2[i-1] + nprocs[i-1]; 700 /* 701 Each message is 1 + nprocs[i] long, and consists of 702 (0) the number of nodes being sent back 703 (1) the local node number, 704 (2) the number of processors sharing it, 705 (3) the processors sharing it 706 */ 707 for (i=0; i<nsends2; i++) { 708 cnt = 1; 709 sends2[starts2[i]] = 0; 710 for (j=0; j<len[i]; j++) { 711 node = recvs[2*i*nmax+2*j]-rstart; 712 if (nownedsenders[node] > 1) { 713 sends2[starts2[i]]++; 714 sends2[starts2[i]+cnt++] = recvs[2*i*nmax+2*j+1]; 715 sends2[starts2[i]+cnt++] = nownedsenders[node]; 716 ierr = PetscMemcpy(&sends2[starts2[i]+cnt],&ownedsenders[starts[node]],nownedsenders[node]*sizeof(int));CHKERRQ(ierr); 717 cnt += nownedsenders[node]; 718 } 719 } 720 } 721 722 /* send the message lengths */ 723 for (i=0; i<nsends2; i++) { 724 ierr = MPI_Send(&nprocs[i],1,MPI_INT,source[i],tag2,comm);CHKERRQ(ierr); 725 } 726 727 /* receive the message lengths */ 728 nrecvs2 = nsends; 729 ierr = PetscMalloc((nrecvs2+1)*sizeof(int),&lens2);CHKERRQ(ierr); 730 ierr = PetscMalloc((nrecvs2+1)*sizeof(int),&starts3);CHKERRQ(ierr); 731 nt = 0; 732 for (i=0; i<nrecvs2; i++) { 733 ierr = MPI_Recv(&lens2[i],1,MPI_INT,dest[i],tag2,comm,&recv_status);CHKERRQ(ierr); 734 nt += lens2[i]; 735 } 736 starts3[0] = 0; 737 for (i=0; i<nrecvs2-1; i++) { 738 starts3[i+1] = starts3[i] + lens2[i]; 739 } 740 ierr = PetscMalloc((nt+1)*sizeof(int),&recvs2);CHKERRQ(ierr); 741 ierr = PetscMalloc((nrecvs2+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr); 742 for (i=0; i<nrecvs2; i++) { 743 ierr = MPI_Irecv(recvs2+starts3[i],lens2[i],MPI_INT,dest[i],tag3,comm,recv_waits+i);CHKERRQ(ierr); 744 } 745 746 /* send the messages */ 747 ierr = PetscMalloc((nsends2+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr); 748 for (i=0; i<nsends2; i++) { 749 ierr = MPI_Isend(sends2+starts2[i],nprocs[i],MPI_INT,source[i],tag3,comm,send_waits+i);CHKERRQ(ierr); 750 } 751 752 /* wait on receives */ 753 ierr = PetscMalloc((nrecvs2+1)*sizeof(MPI_Status),&recv_statuses);CHKERRQ(ierr); 754 ierr = MPI_Waitall(nrecvs2,recv_waits,recv_statuses);CHKERRQ(ierr); 755 ierr = PetscFree(recv_statuses);CHKERRQ(ierr); 756 ierr = PetscFree(recv_waits);CHKERRQ(ierr); 757 ierr = PetscFree(nprocs);CHKERRQ(ierr); 758 759 if (debug) { /* ----------------------------------- */ 760 cnt = 0; 761 for (i=0; i<nrecvs2; i++) { 762 nt = recvs2[cnt++]; 763 for (j=0; j<nt; j++) { 764 ierr = PetscSynchronizedPrintf(comm,"[%d] local node %d number of subdomains %d: ",rank,recvs2[cnt],recvs2[cnt+1]);CHKERRQ(ierr); 765 for (k=0; k<recvs2[cnt+1]; k++) { 766 ierr = PetscSynchronizedPrintf(comm,"%d ",recvs2[cnt+2+k]);CHKERRQ(ierr); 767 } 768 cnt += 2 + recvs2[cnt+1]; 769 ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr); 770 } 771 } 772 ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr); 773 } /* ----------------------------------- */ 774 775 /* count number subdomains for each local node */ 776 ierr = PetscMalloc(size*sizeof(int),&nprocs);CHKERRQ(ierr); 777 ierr = PetscMemzero(nprocs,size*sizeof(int));CHKERRQ(ierr); 778 cnt = 0; 779 for (i=0; i<nrecvs2; i++) { 780 nt = recvs2[cnt++]; 781 for (j=0; j<nt; j++) { 782 for (k=0; k<recvs2[cnt+1]; k++) { 783 nprocs[recvs2[cnt+2+k]]++; 784 } 785 cnt += 2 + recvs2[cnt+1]; 786 } 787 } 788 nt = 0; for (i=0; i<size; i++) nt += (nprocs[i] > 0); 789 *nproc = nt; 790 ierr = PetscMalloc((nt+1)*sizeof(int),procs);CHKERRQ(ierr); 791 ierr = PetscMalloc((nt+1)*sizeof(int),numprocs);CHKERRQ(ierr); 792 ierr = PetscMalloc((nt+1)*sizeof(int*),indices);CHKERRQ(ierr); 793 ierr = PetscMalloc(size*sizeof(int),&bprocs);CHKERRQ(ierr); 794 cnt = 0; 795 for (i=0; i<size; i++) { 796 if (nprocs[i] > 0) { 797 bprocs[i] = cnt; 798 (*procs)[cnt] = i; 799 (*numprocs)[cnt] = nprocs[i]; 800 ierr = PetscMalloc(nprocs[i]*sizeof(int),&(*indices)[cnt]);CHKERRQ(ierr); 801 cnt++; 802 } 803 } 804 805 /* make the list of subdomains for each nontrivial local node */ 806 ierr = PetscMemzero(*numprocs,nt*sizeof(int));CHKERRQ(ierr); 807 cnt = 0; 808 for (i=0; i<nrecvs2; i++) { 809 nt = recvs2[cnt++]; 810 for (j=0; j<nt; j++) { 811 for (k=0; k<recvs2[cnt+1]; k++) { 812 (*indices)[bprocs[recvs2[cnt+2+k]]][(*numprocs)[bprocs[recvs2[cnt+2+k]]]++] = recvs2[cnt]; 813 } 814 cnt += 2 + recvs2[cnt+1]; 815 } 816 } 817 ierr = PetscFree(bprocs);CHKERRQ(ierr); 818 ierr = PetscFree(recvs2);CHKERRQ(ierr); 819 820 /* sort the node indexing by their global numbers */ 821 nt = *nproc; 822 for (i=0; i<nt; i++) { 823 ierr = PetscMalloc(((*numprocs)[i])*sizeof(int),&tmp);CHKERRQ(ierr); 824 for (j=0; j<(*numprocs)[i]; j++) { 825 tmp[j] = lindices[(*indices)[i][j]]; 826 } 827 ierr = PetscSortIntWithArray((*numprocs)[i],tmp,(*indices)[i]);CHKERRQ(ierr); 828 ierr = PetscFree(tmp);CHKERRQ(ierr); 829 } 830 831 if (debug) { /* ----------------------------------- */ 832 nt = *nproc; 833 for (i=0; i<nt; i++) { 834 ierr = PetscSynchronizedPrintf(comm,"[%d] subdomain %d number of indices %d: ",rank,(*procs)[i],(*numprocs)[i]);CHKERRQ(ierr); 835 for (j=0; j<(*numprocs)[i]; j++) { 836 ierr = PetscSynchronizedPrintf(comm,"%d ",(*indices)[i][j]);CHKERRQ(ierr); 837 } 838 ierr = PetscSynchronizedPrintf(comm,"\n");CHKERRQ(ierr); 839 } 840 ierr = PetscSynchronizedFlush(comm);CHKERRQ(ierr); 841 } /* ----------------------------------- */ 842 843 /* wait on sends */ 844 if (nsends2) { 845 ierr = PetscMalloc(nsends2*sizeof(MPI_Status),&send_status);CHKERRQ(ierr); 846 ierr = MPI_Waitall(nsends2,send_waits,send_status);CHKERRQ(ierr); 847 ierr = PetscFree(send_status);CHKERRQ(ierr); 848 } 849 850 ierr = PetscFree(starts3);CHKERRQ(ierr); 851 ierr = PetscFree(dest);CHKERRQ(ierr); 852 ierr = PetscFree(send_waits);CHKERRQ(ierr); 853 854 ierr = PetscFree(nownedsenders);CHKERRQ(ierr); 855 ierr = PetscFree(ownedsenders);CHKERRQ(ierr); 856 ierr = PetscFree(starts);CHKERRQ(ierr); 857 ierr = PetscFree(starts2);CHKERRQ(ierr); 858 ierr = PetscFree(lens2);CHKERRQ(ierr); 859 860 ierr = PetscFree(source);CHKERRQ(ierr); 861 ierr = PetscFree(recvs);CHKERRQ(ierr); 862 ierr = PetscFree(nprocs);CHKERRQ(ierr); 863 ierr = PetscFree(sends2);CHKERRQ(ierr); 864 865 /* put the information about myself as the first entry in the list */ 866 first_procs = (*procs)[0]; 867 first_numprocs = (*numprocs)[0]; 868 first_indices = (*indices)[0]; 869 for (i=0; i<*nproc; i++) { 870 if ((*procs)[i] == rank) { 871 (*procs)[0] = (*procs)[i]; 872 (*numprocs)[0] = (*numprocs)[i]; 873 (*indices)[0] = (*indices)[i]; 874 (*procs)[i] = first_procs; 875 (*numprocs)[i] = first_numprocs; 876 (*indices)[i] = first_indices; 877 break; 878 } 879 } 880 881 PetscFunctionReturn(0); 882 } 883 884 #undef __FUNCT__ 885 #define __FUNCT__ "ISLocalToGlobalMappingRestoreInfo" 886 /*@C 887 ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by ISLocalToGlobalMappingGetInfo() 888 889 Collective on ISLocalToGlobalMapping 890 891 Input Parameters: 892 . mapping - the mapping from local to global indexing 893 894 Output Parameter: 895 + nproc - number of processors that are connected to this one 896 . proc - neighboring processors 897 . numproc - number of indices for each processor 898 - indices - indices of local nodes shared with neighbor (sorted by global numbering) 899 900 Level: advanced 901 902 .seealso: ISLocalToGlobalMappingDestroy(), ISLocalToGlobalMappingCreateIS(), ISLocalToGlobalMappingCreate(), 903 ISLocalToGlobalMappingGetInfo() 904 @*/ 905 int ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping,int *nproc,int **procs,int **numprocs,int ***indices) 906 { 907 int ierr,i; 908 909 PetscFunctionBegin; 910 if (*procs) {ierr = PetscFree(*procs);CHKERRQ(ierr);} 911 if (*numprocs) {ierr = PetscFree(*numprocs);CHKERRQ(ierr);} 912 if (*indices) { 913 if ((*indices)[0]) {ierr = PetscFree((*indices)[0]);CHKERRQ(ierr);} 914 for (i=1; i<*nproc; i++) { 915 if ((*indices)[i]) {ierr = PetscFree((*indices)[i]);CHKERRQ(ierr);} 916 } 917 ierr = PetscFree(*indices);CHKERRQ(ierr); 918 } 919 PetscFunctionReturn(0); 920 } 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939