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