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