1 2 /* 3 This file contains routines for basic map object implementation. 4 */ 5 6 #include <petsc/private/isimpl.h> /*I "petscis.h" I*/ 7 8 /*@ 9 PetscLayoutCreate - Allocates `PetscLayout` object 10 11 Collective 12 13 Input Parameter: 14 . comm - the MPI communicator 15 16 Output Parameter: 17 . map - the new `PetscLayout` 18 19 Level: advanced 20 21 Notes: 22 Typical calling sequence 23 .vb 24 PetscLayoutCreate(MPI_Comm,PetscLayout *); 25 PetscLayoutSetBlockSize(PetscLayout,bs); 26 PetscLayoutSetSize(PetscLayout,N); // or PetscLayoutSetLocalSize(PetscLayout,n); 27 PetscLayoutSetUp(PetscLayout); 28 .ve 29 Alternatively, 30 .vb 31 PetscLayoutCreateFromSizes(comm,n,N,bs,&layout); 32 .ve 33 34 Optionally use any of the following 35 .vb 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 .ve 42 43 The `PetscLayout` object and methods are intended to be used in the PETSc `Vec` and `Mat` implementations; it is often not needed in 44 user codes unless you really gain something in their use. 45 46 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, 47 `PetscLayout`, `PetscLayoutDestroy()`, 48 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`, 49 `PetscLayoutCreateFromSizes()` 50 @*/ 51 PetscErrorCode PetscLayoutCreate(MPI_Comm comm, PetscLayout *map) 52 { 53 PetscFunctionBegin; 54 PetscCall(PetscNew(map)); 55 PetscCallMPI(MPI_Comm_size(comm, &(*map)->size)); 56 (*map)->comm = comm; 57 (*map)->bs = -1; 58 (*map)->n = -1; 59 (*map)->N = -1; 60 (*map)->range = NULL; 61 (*map)->range_alloc = PETSC_TRUE; 62 (*map)->rstart = 0; 63 (*map)->rend = 0; 64 (*map)->setupcalled = PETSC_FALSE; 65 (*map)->oldn = -1; 66 (*map)->oldN = -1; 67 (*map)->oldbs = -1; 68 PetscFunctionReturn(PETSC_SUCCESS); 69 } 70 71 /*@ 72 PetscLayoutCreateFromSizes - Allocates `PetscLayout` object and sets the layout sizes, and sets the layout up. 73 74 Collective 75 76 Input Parameters: 77 + comm - the MPI communicator 78 . n - the local size (or `PETSC_DECIDE`) 79 . N - the global size (or `PETSC_DECIDE`) 80 - bs - the block size (or `PETSC_DECIDE`) 81 82 Output Parameter: 83 . map - the new `PetscLayout` 84 85 Level: advanced 86 87 Note: 88 $ PetscLayoutCreateFromSizes(comm, n, N, bs, &layout); 89 is a shorthand for 90 .vb 91 PetscLayoutCreate(comm, &layout); 92 PetscLayoutSetLocalSize(layout, n); 93 PetscLayoutSetSize(layout, N); 94 PetscLayoutSetBlockSize(layout, bs); 95 PetscLayoutSetUp(layout); 96 .ve 97 98 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayout`, `PetscLayoutDestroy()`, 99 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`, `PetscLayoutCreateFromRanges()` 100 @*/ 101 PetscErrorCode PetscLayoutCreateFromSizes(MPI_Comm comm, PetscInt n, PetscInt N, PetscInt bs, PetscLayout *map) 102 { 103 PetscFunctionBegin; 104 PetscCall(PetscLayoutCreate(comm, map)); 105 PetscCall(PetscLayoutSetLocalSize(*map, n)); 106 PetscCall(PetscLayoutSetSize(*map, N)); 107 PetscCall(PetscLayoutSetBlockSize(*map, bs)); 108 PetscCall(PetscLayoutSetUp(*map)); 109 PetscFunctionReturn(PETSC_SUCCESS); 110 } 111 112 /*@ 113 PetscLayoutDestroy - Frees a `PetscLayout` object and frees its range if that exists. 114 115 Collective 116 117 Input Parameter: 118 . map - the `PetscLayout` 119 120 Level: developer 121 122 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, 123 `PetscLayout`, `PetscLayoutCreate()`, 124 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()` 125 @*/ 126 PetscErrorCode PetscLayoutDestroy(PetscLayout *map) 127 { 128 PetscFunctionBegin; 129 if (!*map) PetscFunctionReturn(PETSC_SUCCESS); 130 if (!(*map)->refcnt--) { 131 if ((*map)->range_alloc) PetscCall(PetscFree((*map)->range)); 132 PetscCall(ISLocalToGlobalMappingDestroy(&(*map)->mapping)); 133 PetscCall(PetscFree((*map))); 134 } 135 *map = NULL; 136 PetscFunctionReturn(PETSC_SUCCESS); 137 } 138 139 /*@ 140 PetscLayoutCreateFromRanges - Creates a new `PetscLayout` with the given ownership ranges and sets it up. 141 142 Collective 143 144 Input Parameters: 145 + comm - the MPI communicator 146 . range - the array of ownership ranges for each rank with length commsize+1 147 . mode - the copy mode for range 148 - bs - the block size (or `PETSC_DECIDE`) 149 150 Output Parameter: 151 . newmap - the new `PetscLayout` 152 153 Level: developer 154 155 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, 156 `PetscLayoutGetLocalSize()`, `PetscLayout`, `PetscLayoutDestroy()`, 157 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`, `PetscLayoutCreateFromSizes()` 158 @*/ 159 PetscErrorCode PetscLayoutCreateFromRanges(MPI_Comm comm, const PetscInt range[], PetscCopyMode mode, PetscInt bs, PetscLayout *newmap) 160 { 161 PetscLayout map; 162 PetscMPIInt rank; 163 164 PetscFunctionBegin; 165 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 166 PetscCall(PetscLayoutCreate(comm, &map)); 167 PetscCall(PetscLayoutSetBlockSize(map, bs)); 168 switch (mode) { 169 case PETSC_COPY_VALUES: 170 PetscCall(PetscMalloc1(map->size + 1, &map->range)); 171 PetscCall(PetscArraycpy(map->range, range, map->size + 1)); 172 break; 173 case PETSC_USE_POINTER: 174 map->range_alloc = PETSC_FALSE; 175 break; 176 default: 177 map->range = (PetscInt *)range; 178 break; 179 } 180 map->rstart = map->range[rank]; 181 map->rend = map->range[rank + 1]; 182 map->n = map->rend - map->rstart; 183 map->N = map->range[map->size]; 184 if (PetscDefined(USE_DEBUG)) { /* just check that n, N and bs are consistent */ 185 PetscInt tmp; 186 PetscCall(MPIU_Allreduce(&map->n, &tmp, 1, MPIU_INT, MPI_SUM, map->comm)); 187 PetscCheck(tmp == map->N, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Sum of local lengths %" PetscInt_FMT " does not equal global length %" PetscInt_FMT ", my local length %" PetscInt_FMT ".\nThe provided PetscLayout is wrong.", tmp, map->N, map->n); 188 if (map->bs > 1) PetscCheck(map->n % map->bs == 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local size %" PetscInt_FMT " must be divisible by blocksize %" PetscInt_FMT, map->n, map->bs); 189 if (map->bs > 1) PetscCheck(map->N % map->bs == 0, map->comm, PETSC_ERR_PLIB, "Global size %" PetscInt_FMT " must be divisible by blocksize %" PetscInt_FMT, map->N, map->bs); 190 } 191 /* lock the layout */ 192 map->setupcalled = PETSC_TRUE; 193 map->oldn = map->n; 194 map->oldN = map->N; 195 map->oldbs = map->bs; 196 *newmap = map; 197 PetscFunctionReturn(PETSC_SUCCESS); 198 } 199 200 /*@ 201 PetscLayoutSetUp - given a map where you have set either the global or local 202 size sets up the map so that it may be used. 203 204 Collective 205 206 Input Parameter: 207 . map - pointer to the map 208 209 Level: developer 210 211 Notes: 212 Typical calling sequence 213 .vb 214 PetscLayoutCreate(MPI_Comm,PetscLayout *); 215 PetscLayoutSetBlockSize(PetscLayout,1); 216 PetscLayoutSetSize(PetscLayout,n) or PetscLayoutSetLocalSize(PetscLayout,N); or both 217 PetscLayoutSetUp(PetscLayout); 218 PetscLayoutGetSize(PetscLayout,PetscInt *); 219 .ve 220 221 If range exists, and local size is not set, everything gets computed from the range. 222 223 If the local size, global size are already set and range exists then this does nothing. 224 225 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, 226 `PetscLayout`, `PetscLayoutDestroy()`, 227 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutCreate()`, `PetscSplitOwnership()` 228 @*/ 229 PetscErrorCode PetscLayoutSetUp(PetscLayout map) 230 { 231 PetscMPIInt rank; 232 PetscInt p; 233 234 PetscFunctionBegin; 235 PetscCheck(!map->setupcalled || !(map->n != map->oldn || map->N != map->oldN), map->comm, PETSC_ERR_ARG_WRONGSTATE, "Layout is already setup with (local=%" PetscInt_FMT ",global=%" PetscInt_FMT "), cannot call setup again with (local=%" PetscInt_FMT ",global=%" PetscInt_FMT ")", 236 map->oldn, map->oldN, map->n, map->N); 237 if (map->setupcalled) PetscFunctionReturn(PETSC_SUCCESS); 238 239 if (map->n > 0 && map->bs > 1) PetscCheck(map->n % map->bs == 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local size %" PetscInt_FMT " must be divisible by blocksize %" PetscInt_FMT, map->n, map->bs); 240 if (map->N > 0 && map->bs > 1) PetscCheck(map->N % map->bs == 0, map->comm, PETSC_ERR_PLIB, "Global size %" PetscInt_FMT " must be divisible by blocksize %" PetscInt_FMT, map->N, map->bs); 241 242 PetscCallMPI(MPI_Comm_rank(map->comm, &rank)); 243 if (map->n > 0) map->n = map->n / PetscAbs(map->bs); 244 if (map->N > 0) map->N = map->N / PetscAbs(map->bs); 245 PetscCall(PetscSplitOwnership(map->comm, &map->n, &map->N)); 246 map->n = map->n * PetscAbs(map->bs); 247 map->N = map->N * PetscAbs(map->bs); 248 if (!map->range) PetscCall(PetscMalloc1(map->size + 1, &map->range)); 249 PetscCallMPI(MPI_Allgather(&map->n, 1, MPIU_INT, map->range + 1, 1, MPIU_INT, map->comm)); 250 251 map->range[0] = 0; 252 for (p = 2; p <= map->size; p++) map->range[p] += map->range[p - 1]; 253 254 map->rstart = map->range[rank]; 255 map->rend = map->range[rank + 1]; 256 257 /* lock the layout */ 258 map->setupcalled = PETSC_TRUE; 259 map->oldn = map->n; 260 map->oldN = map->N; 261 map->oldbs = map->bs; 262 PetscFunctionReturn(PETSC_SUCCESS); 263 } 264 265 /*@ 266 PetscLayoutDuplicate - creates a new `PetscLayout` with the same information as a given one. If the `PetscLayout` already exists it is destroyed first. 267 268 Collective 269 270 Input Parameter: 271 . in - input `PetscLayout` to be duplicated 272 273 Output Parameter: 274 . out - the copy 275 276 Level: developer 277 278 Note: 279 `PetscLayoutSetUp()` does not need to be called on the resulting `PetscLayout` 280 281 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutReference()` 282 @*/ 283 PetscErrorCode PetscLayoutDuplicate(PetscLayout in, PetscLayout *out) 284 { 285 MPI_Comm comm = in->comm; 286 287 PetscFunctionBegin; 288 PetscCall(PetscLayoutDestroy(out)); 289 PetscCall(PetscLayoutCreate(comm, out)); 290 PetscCall(PetscMemcpy(*out, in, sizeof(struct _n_PetscLayout))); 291 if (in->range) { 292 PetscCall(PetscMalloc1((*out)->size + 1, &(*out)->range)); 293 PetscCall(PetscArraycpy((*out)->range, in->range, (*out)->size + 1)); 294 } 295 (*out)->refcnt = 0; 296 PetscFunctionReturn(PETSC_SUCCESS); 297 } 298 299 /*@ 300 PetscLayoutReference - Causes a PETSc `Vec` or `Mat` to share a `PetscLayout` with one that already exists. 301 302 Collective 303 304 Input Parameter: 305 . in - input `PetscLayout` to be copied 306 307 Output Parameter: 308 . out - the reference location 309 310 Level: developer 311 312 Notes: 313 `PetscLayoutSetUp()` does not need to be called on the resulting `PetscLayout` 314 315 If the out location already contains a `PetscLayout` it is destroyed 316 317 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutDuplicate()` 318 @*/ 319 PetscErrorCode PetscLayoutReference(PetscLayout in, PetscLayout *out) 320 { 321 PetscFunctionBegin; 322 in->refcnt++; 323 PetscCall(PetscLayoutDestroy(out)); 324 *out = in; 325 PetscFunctionReturn(PETSC_SUCCESS); 326 } 327 328 /*@ 329 PetscLayoutSetISLocalToGlobalMapping - sets a `ISLocalGlobalMapping` into a `PetscLayout` 330 331 Collective 332 333 Input Parameters: 334 + in - input `PetscLayout` 335 - ltog - the local to global mapping 336 337 Level: developer 338 339 Notes: 340 `PetscLayoutSetUp()` does not need to be called on the resulting `PetscLayout` 341 342 If the `PetscLayout` already contains a `ISLocalGlobalMapping` it is destroyed 343 344 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutDuplicate()` 345 @*/ 346 PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in, ISLocalToGlobalMapping ltog) 347 { 348 PetscFunctionBegin; 349 if (ltog) { 350 PetscInt bs; 351 352 PetscCall(ISLocalToGlobalMappingGetBlockSize(ltog, &bs)); 353 PetscCheck(in->bs <= 0 || bs == 1 || in->bs == bs, in->comm, PETSC_ERR_PLIB, "Blocksize of layout %" PetscInt_FMT " must match that of mapping %" PetscInt_FMT " (or the latter must be 1)", in->bs, bs); 354 PetscCall(PetscObjectReference((PetscObject)ltog)); 355 } 356 PetscCall(ISLocalToGlobalMappingDestroy(&in->mapping)); 357 in->mapping = ltog; 358 PetscFunctionReturn(PETSC_SUCCESS); 359 } 360 361 /*@ 362 PetscLayoutSetLocalSize - Sets the local size for a `PetscLayout` object. 363 364 Collective 365 366 Input Parameters: 367 + map - pointer to the map 368 - n - the local size 369 370 Level: developer 371 372 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetUp()` 373 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()` 374 @*/ 375 PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map, PetscInt n) 376 { 377 PetscFunctionBegin; 378 PetscCheck(map->bs <= 1 || (n % map->bs) == 0, map->comm, PETSC_ERR_ARG_INCOMP, "Local size %" PetscInt_FMT " not compatible with block size %" PetscInt_FMT, n, map->bs); 379 map->n = n; 380 PetscFunctionReturn(PETSC_SUCCESS); 381 } 382 383 /*@ 384 PetscLayoutGetLocalSize - Gets the local size for a `PetscLayout` object. 385 386 Not Collective 387 388 Input Parameter: 389 . map - pointer to the map 390 391 Output Parameter: 392 . n - the local size 393 394 Level: developer 395 396 Note: 397 Call this after the call to `PetscLayoutSetUp()` 398 399 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()` 400 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()` 401 @*/ 402 PetscErrorCode PetscLayoutGetLocalSize(PetscLayout map, PetscInt *n) 403 { 404 PetscFunctionBegin; 405 *n = map->n; 406 PetscFunctionReturn(PETSC_SUCCESS); 407 } 408 409 /*@ 410 PetscLayoutSetSize - Sets the global size for a `PetscLayout` object. 411 412 Logically Collective 413 414 Input Parameters: 415 + map - pointer to the map 416 - n - the global size 417 418 Level: developer 419 420 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()` 421 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()` 422 @*/ 423 PetscErrorCode PetscLayoutSetSize(PetscLayout map, PetscInt n) 424 { 425 PetscFunctionBegin; 426 map->N = n; 427 PetscFunctionReturn(PETSC_SUCCESS); 428 } 429 430 /*@ 431 PetscLayoutGetSize - Gets the global size for a `PetscLayout` object. 432 433 Not Collective 434 435 Input Parameter: 436 . map - pointer to the map 437 438 Output Parameter: 439 . n - the global size 440 441 Level: developer 442 443 Note: 444 Call this after the call to `PetscLayoutSetUp()` 445 446 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutSetUp()` 447 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()` 448 @*/ 449 PetscErrorCode PetscLayoutGetSize(PetscLayout map, PetscInt *n) 450 { 451 PetscFunctionBegin; 452 *n = map->N; 453 PetscFunctionReturn(PETSC_SUCCESS); 454 } 455 456 /*@ 457 PetscLayoutSetBlockSize - Sets the block size for a `PetscLayout` object. 458 459 Logically Collective 460 461 Input Parameters: 462 + map - pointer to the map 463 - bs - the size 464 465 Level: developer 466 467 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetBlockSize()`, 468 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()` 469 @*/ 470 PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map, PetscInt bs) 471 { 472 PetscFunctionBegin; 473 if (bs < 0) PetscFunctionReturn(PETSC_SUCCESS); 474 PetscCheck(map->n <= 0 || (map->n % bs) == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Local size %" PetscInt_FMT " not compatible with block size %" PetscInt_FMT, map->n, bs); 475 if (map->mapping) { 476 PetscInt obs; 477 478 PetscCall(ISLocalToGlobalMappingGetBlockSize(map->mapping, &obs)); 479 if (obs > 1) PetscCall(ISLocalToGlobalMappingSetBlockSize(map->mapping, bs)); 480 } 481 map->bs = bs; 482 PetscFunctionReturn(PETSC_SUCCESS); 483 } 484 485 /*@ 486 PetscLayoutGetBlockSize - Gets the block size for a `PetscLayout` object. 487 488 Not Collective 489 490 Input Parameter: 491 . map - pointer to the map 492 493 Output Parameter: 494 . bs - the size 495 496 Level: developer 497 498 Notes: 499 Call this after the call to `PetscLayoutSetUp()` 500 501 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutSetUp()` 502 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetSize()` 503 @*/ 504 PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map, PetscInt *bs) 505 { 506 PetscFunctionBegin; 507 *bs = PetscAbs(map->bs); 508 PetscFunctionReturn(PETSC_SUCCESS); 509 } 510 511 /*@ 512 PetscLayoutGetRange - gets the range of values owned by this process 513 514 Not Collective 515 516 Input Parameter: 517 . map - pointer to the map 518 519 Output Parameters: 520 + rstart - first index owned by this process 521 - rend - one more than the last index owned by this process 522 523 Level: developer 524 525 Note: 526 Call this after the call to `PetscLayoutSetUp()` 527 528 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`, 529 `PetscLayoutGetSize()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutSetUp()` 530 @*/ 531 PetscErrorCode PetscLayoutGetRange(PetscLayout map, PetscInt *rstart, PetscInt *rend) 532 { 533 PetscFunctionBegin; 534 if (rstart) *rstart = map->rstart; 535 if (rend) *rend = map->rend; 536 PetscFunctionReturn(PETSC_SUCCESS); 537 } 538 539 /*@C 540 PetscLayoutGetRanges - gets the ranges of values owned by all processes 541 542 Not Collective 543 544 Input Parameter: 545 . map - pointer to the map 546 547 Output Parameter: 548 . range - start of each processors range of indices (the final entry is one more than the 549 last index on the last process) 550 551 Level: developer 552 553 Note: 554 Call this after the call to `PetscLayoutSetUp()` 555 556 Fortran Notes: 557 In Fortran, use PetscLayoutGetRangesF90() 558 559 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`, 560 `PetscLayoutGetSize()`, `PetscLayoutGetRange()`, `PetscLayoutSetBlockSize()`, `PetscLayoutSetUp()` 561 @*/ 562 PetscErrorCode PetscLayoutGetRanges(PetscLayout map, const PetscInt *range[]) 563 { 564 PetscFunctionBegin; 565 *range = map->range; 566 PetscFunctionReturn(PETSC_SUCCESS); 567 } 568 569 /*@ 570 PetscLayoutCompare - Compares two layouts 571 572 Not Collective 573 574 Input Parameters: 575 + mapa - pointer to the first map 576 - mapb - pointer to the second map 577 578 Output Parameter: 579 . congruent - `PETSC_TRUE` if the two layouts are congruent, `PETSC_FALSE` otherwise 580 581 Level: beginner 582 583 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetBlockSize()`, 584 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()` 585 @*/ 586 PetscErrorCode PetscLayoutCompare(PetscLayout mapa, PetscLayout mapb, PetscBool *congruent) 587 { 588 PetscFunctionBegin; 589 *congruent = PETSC_FALSE; 590 if (mapa->N == mapb->N && mapa->range && mapb->range && mapa->size == mapb->size) PetscCall(PetscArraycmp(mapa->range, mapb->range, mapa->size + 1, congruent)); 591 PetscFunctionReturn(PETSC_SUCCESS); 592 } 593