1 2 /* 3 This file contains routines for basic map object implementation. 4 */ 5 6 #include <petscis.h> /*I "petscis.h" I*/ 7 #include <petscsf.h> 8 #include <petsc/private/isimpl.h> 9 10 /*@ 11 PetscLayoutCreate - Allocates PetscLayout space and sets the PetscLayout contents to the default. 12 13 Collective 14 15 Input Parameters: 16 . comm - the MPI communicator 17 18 Output Parameters: 19 . map - the new PetscLayout 20 21 Level: advanced 22 23 Notes: 24 Typical calling sequence 25 .vb 26 PetscLayoutCreate(MPI_Comm,PetscLayout *); 27 PetscLayoutSetBlockSize(PetscLayout,bs); 28 PetscLayoutSetSize(PetscLayout,N); // or PetscLayoutSetLocalSize(PetscLayout,n); 29 PetscLayoutSetUp(PetscLayout); 30 .ve 31 Alternatively, 32 $ PetscLayoutCreateFromSizes(comm,n,N,bs,&layout); 33 34 Optionally use any of the following: 35 36 + PetscLayoutGetSize(PetscLayout,PetscInt *); 37 . PetscLayoutGetLocalSize(PetscLayout,PetscInt *); 38 . PetscLayoutGetRange(PetscLayout,PetscInt *rstart,PetscInt *rend); 39 . PetscLayoutGetRanges(PetscLayout,const PetscInt *range[]); 40 - PetscLayoutDestroy(PetscLayout*); 41 42 The PetscLayout object and methods are intended to be used in the PETSc Vec and Mat implementions; it is often not needed in 43 user codes unless you really gain something in their use. 44 45 .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(), 46 PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp(), 47 PetscLayoutCreateFromSizes() 48 49 @*/ 50 PetscErrorCode PetscLayoutCreate(MPI_Comm comm,PetscLayout *map) 51 { 52 PetscErrorCode ierr; 53 54 PetscFunctionBegin; 55 ierr = PetscNew(map);CHKERRQ(ierr); 56 ierr = MPI_Comm_size(comm, &(*map)->size);CHKERRQ(ierr); 57 (*map)->comm = comm; 58 (*map)->bs = -1; 59 (*map)->n = -1; 60 (*map)->N = -1; 61 (*map)->range = NULL; 62 (*map)->range_alloc = PETSC_TRUE; 63 (*map)->rstart = 0; 64 (*map)->rend = 0; 65 (*map)->setupcalled = PETSC_FALSE; 66 (*map)->oldn = -1; 67 (*map)->oldN = -1; 68 (*map)->oldbs = -1; 69 PetscFunctionReturn(0); 70 } 71 72 /*@ 73 PetscLayoutCreateFromSizes - Allocates PetscLayout space, sets the layout sizes, and sets the layout up. 74 75 Collective 76 77 Input Parameters: 78 + comm - the MPI communicator 79 . n - the local size (or PETSC_DECIDE) 80 . N - the global size (or PETSC_DECIDE) 81 - bs - the block size (or PETSC_DECIDE) 82 83 Output Parameters: 84 . map - the new PetscLayout 85 86 Level: advanced 87 88 Notes: 89 $ PetscLayoutCreateFromSizes(comm,n,N,bs,&layout); 90 is a shorthand for 91 .vb 92 PetscLayoutCreate(comm,&layout); 93 PetscLayoutSetLocalSize(layout,n); 94 PetscLayoutSetSize(layout,N); 95 PetscLayoutSetBlockSize(layout,bs); 96 PetscLayoutSetUp(layout); 97 .ve 98 99 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(), 100 PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp(), PetscLayoutCreateFromRanges() 101 102 @*/ 103 PetscErrorCode PetscLayoutCreateFromSizes(MPI_Comm comm,PetscInt n,PetscInt N,PetscInt bs,PetscLayout *map) 104 { 105 PetscErrorCode ierr; 106 107 PetscFunctionBegin; 108 ierr = PetscLayoutCreate(comm, map);CHKERRQ(ierr); 109 ierr = PetscLayoutSetLocalSize(*map, n);CHKERRQ(ierr); 110 ierr = PetscLayoutSetSize(*map, N);CHKERRQ(ierr); 111 ierr = PetscLayoutSetBlockSize(*map, bs);CHKERRQ(ierr); 112 ierr = PetscLayoutSetUp(*map);CHKERRQ(ierr); 113 PetscFunctionReturn(0); 114 } 115 116 /*@ 117 PetscLayoutDestroy - Frees a map object and frees its range if that exists. 118 119 Collective 120 121 Input Parameters: 122 . map - the PetscLayout 123 124 Level: developer 125 126 Note: 127 The PetscLayout object and methods are intended to be used in the PETSc Vec and Mat implementions; it is 128 recommended they not be used in user codes unless you really gain something in their use. 129 130 .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutCreate(), 131 PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp() 132 133 @*/ 134 PetscErrorCode PetscLayoutDestroy(PetscLayout *map) 135 { 136 PetscErrorCode ierr; 137 138 PetscFunctionBegin; 139 if (!*map) PetscFunctionReturn(0); 140 if (!(*map)->refcnt--) { 141 if ((*map)->range_alloc) {ierr = PetscFree((*map)->range);CHKERRQ(ierr);} 142 ierr = ISLocalToGlobalMappingDestroy(&(*map)->mapping);CHKERRQ(ierr); 143 ierr = PetscFree((*map));CHKERRQ(ierr); 144 } 145 *map = NULL; 146 PetscFunctionReturn(0); 147 } 148 149 /*@ 150 PetscLayoutCreateFromRanges - Creates a new PetscLayout with the given ownership ranges and sets it up. 151 152 Collective 153 154 Input Parameters: 155 + comm - the MPI communicator 156 . range - the array of ownership ranges for each rank with length commsize+1 157 . mode - the copy mode for range 158 - bs - the block size (or PETSC_DECIDE) 159 160 Output Parameters: 161 . newmap - the new PetscLayout 162 163 Level: developer 164 165 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(), 166 PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp(), PetscLayoutCreateFromSizes() 167 168 @*/ 169 PetscErrorCode PetscLayoutCreateFromRanges(MPI_Comm comm,const PetscInt range[],PetscCopyMode mode,PetscInt bs,PetscLayout *newmap) 170 { 171 PetscLayout map; 172 PetscMPIInt rank; 173 PetscErrorCode ierr; 174 175 PetscFunctionBegin; 176 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 177 ierr = PetscLayoutCreate(comm, &map);CHKERRQ(ierr); 178 ierr = PetscLayoutSetBlockSize(map, bs);CHKERRQ(ierr); 179 switch (mode) { 180 case PETSC_COPY_VALUES: 181 ierr = PetscMalloc1(map->size+1, &map->range);CHKERRQ(ierr); 182 ierr = PetscArraycpy(map->range, range, map->size+1);CHKERRQ(ierr); 183 break; 184 case PETSC_USE_POINTER: 185 map->range_alloc = PETSC_FALSE; 186 default: 187 map->range = (PetscInt*) range; 188 break; 189 } 190 map->rstart = map->range[rank]; 191 map->rend = map->range[rank+1]; 192 map->n = map->rend - map->rstart; 193 map->N = map->range[map->size]; 194 if (PetscDefined(USE_DEBUG)) { /* just check that n, N and bs are consistent */ 195 PetscInt tmp; 196 ierr = MPIU_Allreduce(&map->n,&tmp,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr); 197 if (tmp != map->N) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Sum of local lengths %D does not equal global length %D, my local length %D.\nThe provided PetscLayout is wrong.",tmp,map->N,map->n); 198 if (map->bs > 1) { 199 if (map->n % map->bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local size %D must be divisible by blocksize %D",map->n,map->bs); 200 } 201 if (map->bs > 1) { 202 if (map->N % map->bs) SETERRQ2(map->comm,PETSC_ERR_PLIB,"Global size %D must be divisible by blocksize %D",map->N,map->bs); 203 } 204 } 205 /* lock the layout */ 206 map->setupcalled = PETSC_TRUE; 207 map->oldn = map->n; 208 map->oldN = map->N; 209 map->oldbs = map->bs; 210 *newmap = map; 211 PetscFunctionReturn(0); 212 } 213 214 /*@ 215 PetscLayoutSetUp - given a map where you have set either the global or local 216 size sets up the map so that it may be used. 217 218 Collective 219 220 Input Parameters: 221 . map - pointer to the map 222 223 Level: developer 224 225 Notes: 226 Typical calling sequence 227 $ PetscLayoutCreate(MPI_Comm,PetscLayout *); 228 $ PetscLayoutSetBlockSize(PetscLayout,1); 229 $ PetscLayoutSetSize(PetscLayout,n) or PetscLayoutSetLocalSize(PetscLayout,N); or both 230 $ PetscLayoutSetUp(PetscLayout); 231 $ PetscLayoutGetSize(PetscLayout,PetscInt *); 232 233 If range exists, and local size is not set, everything gets computed from the range. 234 235 If the local size, global size are already set and range exists then this does nothing. 236 237 .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(), 238 PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutCreate() 239 @*/ 240 PetscErrorCode PetscLayoutSetUp(PetscLayout map) 241 { 242 PetscMPIInt rank; 243 PetscInt p; 244 PetscErrorCode ierr; 245 246 PetscFunctionBegin; 247 if (map->setupcalled && (map->n != map->oldn || map->N != map->oldN)) SETERRQ4(map->comm,PETSC_ERR_ARG_WRONGSTATE,"Layout is already setup with (local=%D,global=%D), cannot call setup again with (local=%D,global=%D)", map->oldn, map->oldN, map->n, map->N); 248 if (map->setupcalled) PetscFunctionReturn(0); 249 250 if (map->n > 0 && map->bs > 1) { 251 if (map->n % map->bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local size %D must be divisible by blocksize %D",map->n,map->bs); 252 } 253 if (map->N > 0 && map->bs > 1) { 254 if (map->N % map->bs) SETERRQ2(map->comm,PETSC_ERR_PLIB,"Global size %D must be divisible by blocksize %D",map->N,map->bs); 255 } 256 257 ierr = MPI_Comm_rank(map->comm, &rank);CHKERRMPI(ierr); 258 if (map->n > 0) map->n = map->n/PetscAbs(map->bs); 259 if (map->N > 0) map->N = map->N/PetscAbs(map->bs); 260 ierr = PetscSplitOwnership(map->comm,&map->n,&map->N);CHKERRQ(ierr); 261 map->n = map->n*PetscAbs(map->bs); 262 map->N = map->N*PetscAbs(map->bs); 263 if (!map->range) { 264 ierr = PetscMalloc1(map->size+1, &map->range);CHKERRQ(ierr); 265 } 266 ierr = MPI_Allgather(&map->n, 1, MPIU_INT, map->range+1, 1, MPIU_INT, map->comm);CHKERRMPI(ierr); 267 268 map->range[0] = 0; 269 for (p = 2; p <= map->size; p++) map->range[p] += map->range[p-1]; 270 271 map->rstart = map->range[rank]; 272 map->rend = map->range[rank+1]; 273 274 /* lock the layout */ 275 map->setupcalled = PETSC_TRUE; 276 map->oldn = map->n; 277 map->oldN = map->N; 278 map->oldbs = map->bs; 279 PetscFunctionReturn(0); 280 } 281 282 /*@ 283 PetscLayoutDuplicate - creates a new PetscLayout with the same information as a given one. If the PetscLayout already exists it is destroyed first. 284 285 Collective on PetscLayout 286 287 Input Parameter: 288 . in - input PetscLayout to be duplicated 289 290 Output Parameter: 291 . out - the copy 292 293 Level: developer 294 295 Notes: 296 PetscLayoutSetUp() does not need to be called on the resulting PetscLayout 297 298 .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutReference() 299 @*/ 300 PetscErrorCode PetscLayoutDuplicate(PetscLayout in,PetscLayout *out) 301 { 302 PetscErrorCode ierr; 303 MPI_Comm comm = in->comm; 304 305 PetscFunctionBegin; 306 ierr = PetscLayoutDestroy(out);CHKERRQ(ierr); 307 ierr = PetscLayoutCreate(comm,out);CHKERRQ(ierr); 308 ierr = PetscMemcpy(*out,in,sizeof(struct _n_PetscLayout));CHKERRQ(ierr); 309 if (in->range) { 310 ierr = PetscMalloc1((*out)->size+1,&(*out)->range);CHKERRQ(ierr); 311 ierr = PetscArraycpy((*out)->range,in->range,(*out)->size+1);CHKERRQ(ierr); 312 } 313 (*out)->refcnt = 0; 314 PetscFunctionReturn(0); 315 } 316 317 /*@ 318 PetscLayoutReference - Causes a PETSc Vec or Mat to share a PetscLayout with one that already exists. Used by Vec/MatDuplicate_XXX() 319 320 Collective on PetscLayout 321 322 Input Parameter: 323 . in - input PetscLayout to be copied 324 325 Output Parameter: 326 . out - the reference location 327 328 Level: developer 329 330 Notes: 331 PetscLayoutSetUp() does not need to be called on the resulting PetscLayout 332 333 If the out location already contains a PetscLayout it is destroyed 334 335 .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate() 336 @*/ 337 PetscErrorCode PetscLayoutReference(PetscLayout in,PetscLayout *out) 338 { 339 PetscErrorCode ierr; 340 341 PetscFunctionBegin; 342 in->refcnt++; 343 ierr = PetscLayoutDestroy(out);CHKERRQ(ierr); 344 *out = in; 345 PetscFunctionReturn(0); 346 } 347 348 /*@ 349 PetscLayoutSetISLocalToGlobalMapping - sets a ISLocalGlobalMapping into a PetscLayout 350 351 Collective on PetscLayout 352 353 Input Parameter: 354 + in - input PetscLayout 355 - ltog - the local to global mapping 356 357 358 Level: developer 359 360 Notes: 361 PetscLayoutSetUp() does not need to be called on the resulting PetscLayout 362 363 If the ltog location already contains a PetscLayout it is destroyed 364 365 .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate() 366 @*/ 367 PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in,ISLocalToGlobalMapping ltog) 368 { 369 PetscErrorCode ierr; 370 PetscInt bs; 371 372 PetscFunctionBegin; 373 ierr = ISLocalToGlobalMappingGetBlockSize(ltog,&bs);CHKERRQ(ierr); 374 if (in->bs > 0 && (bs != 1) && in->bs != bs) SETERRQ2(in->comm,PETSC_ERR_PLIB,"Blocksize of layout %D must match that of mapping %D (or the latter must be 1)",in->bs,bs); 375 ierr = PetscObjectReference((PetscObject)ltog);CHKERRQ(ierr); 376 ierr = ISLocalToGlobalMappingDestroy(&in->mapping);CHKERRQ(ierr); 377 in->mapping = ltog; 378 PetscFunctionReturn(0); 379 } 380 381 /*@ 382 PetscLayoutSetLocalSize - Sets the local size for a PetscLayout object. 383 384 Collective on PetscLayout 385 386 Input Parameters: 387 + map - pointer to the map 388 - n - the local size 389 390 Level: developer 391 392 Notes: 393 Call this after the call to PetscLayoutCreate() 394 395 .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp() 396 PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize() 397 @*/ 398 PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map,PetscInt n) 399 { 400 PetscFunctionBegin; 401 if (map->bs > 1 && n % map->bs) SETERRQ2(map->comm,PETSC_ERR_ARG_INCOMP,"Local size %D not compatible with block size %D",n,map->bs); 402 map->n = n; 403 PetscFunctionReturn(0); 404 } 405 406 /*@C 407 PetscLayoutGetLocalSize - Gets the local size for a PetscLayout object. 408 409 Not Collective 410 411 Input Parameters: 412 . map - pointer to the map 413 414 Output Parameters: 415 . n - the local size 416 417 Level: developer 418 419 Notes: 420 Call this after the call to PetscLayoutSetUp() 421 422 Fortran Notes: 423 Not available from Fortran 424 425 .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp() 426 PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize() 427 428 @*/ 429 PetscErrorCode PetscLayoutGetLocalSize(PetscLayout map,PetscInt *n) 430 { 431 PetscFunctionBegin; 432 *n = map->n; 433 PetscFunctionReturn(0); 434 } 435 436 /*@ 437 PetscLayoutSetSize - Sets the global size for a PetscLayout object. 438 439 Logically Collective on PetscLayout 440 441 Input Parameters: 442 + map - pointer to the map 443 - n - the global size 444 445 Level: developer 446 447 Notes: 448 Call this after the call to PetscLayoutCreate() 449 450 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetSize(), PetscLayoutSetUp() 451 PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize() 452 @*/ 453 PetscErrorCode PetscLayoutSetSize(PetscLayout map,PetscInt n) 454 { 455 PetscFunctionBegin; 456 map->N = n; 457 PetscFunctionReturn(0); 458 } 459 460 /*@ 461 PetscLayoutGetSize - Gets the global size for a PetscLayout object. 462 463 Not Collective 464 465 Input Parameters: 466 . map - pointer to the map 467 468 Output Parameters: 469 . n - the global size 470 471 Level: developer 472 473 Notes: 474 Call this after the call to PetscLayoutSetUp() 475 476 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp() 477 PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize() 478 @*/ 479 PetscErrorCode PetscLayoutGetSize(PetscLayout map,PetscInt *n) 480 { 481 PetscFunctionBegin; 482 *n = map->N; 483 PetscFunctionReturn(0); 484 } 485 486 /*@ 487 PetscLayoutSetBlockSize - Sets the block size for a PetscLayout object. 488 489 Logically Collective on PetscLayout 490 491 Input Parameters: 492 + map - pointer to the map 493 - bs - the size 494 495 Level: developer 496 497 Notes: 498 Call this after the call to PetscLayoutCreate() 499 500 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(), 501 PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp() 502 @*/ 503 PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map,PetscInt bs) 504 { 505 PetscFunctionBegin; 506 if (bs < 0) PetscFunctionReturn(0); 507 if (map->n > 0 && map->n % bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Local size %D not compatible with block size %D",map->n,bs); 508 if (map->mapping) { 509 PetscInt obs; 510 PetscErrorCode ierr; 511 512 ierr = ISLocalToGlobalMappingGetBlockSize(map->mapping,&obs);CHKERRQ(ierr); 513 if (obs > 1) { 514 ierr = ISLocalToGlobalMappingSetBlockSize(map->mapping,bs);CHKERRQ(ierr); 515 } 516 } 517 map->bs = bs; 518 PetscFunctionReturn(0); 519 } 520 521 /*@ 522 PetscLayoutGetBlockSize - Gets the block size for a PetscLayout object. 523 524 Not Collective 525 526 Input Parameters: 527 . map - pointer to the map 528 529 Output Parameters: 530 . bs - the size 531 532 Level: developer 533 534 Notes: 535 Call this after the call to PetscLayoutSetUp() 536 537 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp() 538 PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize() 539 @*/ 540 PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map,PetscInt *bs) 541 { 542 PetscFunctionBegin; 543 *bs = PetscAbs(map->bs); 544 PetscFunctionReturn(0); 545 } 546 547 /*@ 548 PetscLayoutGetRange - gets the range of values owned by this process 549 550 Not Collective 551 552 Input Parameters: 553 . map - pointer to the map 554 555 Output Parameters: 556 + rstart - first index owned by this process 557 - rend - one more than the last index owned by this process 558 559 Level: developer 560 561 Notes: 562 Call this after the call to PetscLayoutSetUp() 563 564 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), 565 PetscLayoutGetSize(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp() 566 @*/ 567 PetscErrorCode PetscLayoutGetRange(PetscLayout map,PetscInt *rstart,PetscInt *rend) 568 { 569 PetscFunctionBegin; 570 if (rstart) *rstart = map->rstart; 571 if (rend) *rend = map->rend; 572 PetscFunctionReturn(0); 573 } 574 575 /*@C 576 PetscLayoutGetRanges - gets the range of values owned by all processes 577 578 Not Collective 579 580 Input Parameters: 581 . map - pointer to the map 582 583 Output Parameters: 584 . range - start of each processors range of indices (the final entry is one more then the 585 last index on the last process) 586 587 Level: developer 588 589 Notes: 590 Call this after the call to PetscLayoutSetUp() 591 592 Fortran Notes: 593 Not available from Fortran 594 595 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), 596 PetscLayoutGetSize(), PetscLayoutGetRange(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp() 597 598 @*/ 599 PetscErrorCode PetscLayoutGetRanges(PetscLayout map,const PetscInt *range[]) 600 { 601 PetscFunctionBegin; 602 *range = map->range; 603 PetscFunctionReturn(0); 604 } 605 606 /*@C 607 PetscLayoutsCreateSF - Creates a parallel star forest mapping two PetscLayout objects 608 609 Collective 610 611 Input Arguments: 612 + rmap - PetscLayout defining the global root space 613 - lmap - PetscLayout defining the global leaf space 614 615 Output Arguments: 616 . sf - The parallel star forest 617 618 Level: intermediate 619 620 .seealso: PetscSFCreate(), PetscLayoutCreate(), PetscSFSetGraphLayout() 621 @*/ 622 PetscErrorCode PetscLayoutsCreateSF(PetscLayout rmap, PetscLayout lmap, PetscSF* sf) 623 { 624 PetscErrorCode ierr; 625 PetscInt i,nroots,nleaves = 0; 626 PetscInt rN, lst, len; 627 PetscMPIInt owner = -1; 628 PetscSFNode *remote; 629 MPI_Comm rcomm = rmap->comm; 630 MPI_Comm lcomm = lmap->comm; 631 PetscMPIInt flg; 632 633 PetscFunctionBegin; 634 PetscValidPointer(sf,3); 635 if (!rmap->setupcalled) SETERRQ(rcomm,PETSC_ERR_ARG_WRONGSTATE,"Root layout not setup"); 636 if (!lmap->setupcalled) SETERRQ(lcomm,PETSC_ERR_ARG_WRONGSTATE,"Leaf layout not setup"); 637 ierr = MPI_Comm_compare(rcomm,lcomm,&flg);CHKERRMPI(ierr); 638 if (flg != MPI_CONGRUENT && flg != MPI_IDENT) SETERRQ(rcomm,PETSC_ERR_SUP,"cannot map two layouts with non-matching communicators"); 639 ierr = PetscSFCreate(rcomm,sf);CHKERRQ(ierr); 640 ierr = PetscLayoutGetLocalSize(rmap,&nroots);CHKERRQ(ierr); 641 ierr = PetscLayoutGetSize(rmap,&rN);CHKERRQ(ierr); 642 ierr = PetscLayoutGetRange(lmap,&lst,&len);CHKERRQ(ierr); 643 ierr = PetscMalloc1(len-lst,&remote);CHKERRQ(ierr); 644 for (i = lst; i < len && i < rN; i++) { 645 if (owner < -1 || i >= rmap->range[owner+1]) { 646 ierr = PetscLayoutFindOwner(rmap,i,&owner);CHKERRQ(ierr); 647 } 648 remote[nleaves].rank = owner; 649 remote[nleaves].index = i - rmap->range[owner]; 650 nleaves++; 651 } 652 ierr = PetscSFSetGraph(*sf,nroots,nleaves,NULL,PETSC_OWN_POINTER,remote,PETSC_COPY_VALUES);CHKERRQ(ierr); 653 ierr = PetscFree(remote);CHKERRQ(ierr); 654 PetscFunctionReturn(0); 655 } 656 657 /*@ 658 PetscLayoutCompare - Compares two layouts 659 660 Not Collective 661 662 Input Parameters: 663 + mapa - pointer to the first map 664 - mapb - pointer to the second map 665 666 Output Parameters: 667 . congruent - PETSC_TRUE if the two layouts are congruent, PETSC_FALSE otherwise 668 669 Level: beginner 670 671 Notes: 672 673 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(), 674 PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp() 675 @*/ 676 PetscErrorCode PetscLayoutCompare(PetscLayout mapa,PetscLayout mapb,PetscBool *congruent) 677 { 678 PetscErrorCode ierr; 679 680 PetscFunctionBegin; 681 *congruent = PETSC_FALSE; 682 if (mapa->N == mapb->N && mapa->range && mapb->range && mapa->size == mapb->size) { 683 ierr = PetscArraycmp(mapa->range,mapb->range,mapa->size+1,congruent);CHKERRQ(ierr); 684 } 685 PetscFunctionReturn(0); 686 } 687 688 /* TODO: handle nooffprocentries like MatZeroRowsMapLocal_Private, since this code is the same */ 689 PetscErrorCode PetscLayoutMapLocal(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs) 690 { 691 PetscInt *owners = map->range; 692 PetscInt n = map->n; 693 PetscSF sf; 694 PetscInt *lidxs,*work = NULL; 695 PetscSFNode *ridxs; 696 PetscMPIInt rank, p = 0; 697 PetscInt r, len = 0; 698 PetscErrorCode ierr; 699 700 PetscFunctionBegin; 701 if (on) *on = 0; /* squelch -Wmaybe-uninitialized */ 702 /* Create SF where leaves are input idxs and roots are owned idxs */ 703 ierr = MPI_Comm_rank(map->comm,&rank);CHKERRMPI(ierr); 704 ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr); 705 for (r = 0; r < n; ++r) lidxs[r] = -1; 706 ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr); 707 for (r = 0; r < N; ++r) { 708 const PetscInt idx = idxs[r]; 709 if (idx < 0 || map->N <= idx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Index %D out of range [0,%D)",idx,map->N); 710 if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */ 711 ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr); 712 } 713 ridxs[r].rank = p; 714 ridxs[r].index = idxs[r] - owners[p]; 715 } 716 ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr); 717 ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr); 718 ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr); 719 ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr); 720 if (ogidxs) { /* communicate global idxs */ 721 PetscInt cum = 0,start,*work2; 722 723 ierr = PetscMalloc1(n,&work);CHKERRQ(ierr); 724 ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr); 725 for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++; 726 ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRMPI(ierr); 727 start -= cum; 728 cum = 0; 729 for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++; 730 ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr); 731 ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr); 732 ierr = PetscFree(work2);CHKERRQ(ierr); 733 } 734 ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 735 /* Compress and put in indices */ 736 for (r = 0; r < n; ++r) 737 if (lidxs[r] >= 0) { 738 if (work) work[len] = work[r]; 739 lidxs[len++] = r; 740 } 741 if (on) *on = len; 742 if (oidxs) *oidxs = lidxs; 743 if (ogidxs) *ogidxs = work; 744 PetscFunctionReturn(0); 745 } 746