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 .vb 88 PetscLayoutCreateFromSizes(comm, n, N, bs, &layout); 89 .ve 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: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayout`, `PetscLayoutDestroy()`, 100 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`, `PetscLayoutCreateFromRanges()` 101 @*/ 102 PetscErrorCode PetscLayoutCreateFromSizes(MPI_Comm comm, PetscInt n, PetscInt N, PetscInt bs, PetscLayout *map) 103 { 104 PetscFunctionBegin; 105 PetscCall(PetscLayoutCreate(comm, map)); 106 PetscCall(PetscLayoutSetLocalSize(*map, n)); 107 PetscCall(PetscLayoutSetSize(*map, N)); 108 PetscCall(PetscLayoutSetBlockSize(*map, bs)); 109 PetscCall(PetscLayoutSetUp(*map)); 110 PetscFunctionReturn(PETSC_SUCCESS); 111 } 112 113 /*@ 114 PetscLayoutDestroy - Frees a `PetscLayout` object and frees its range if that exists. 115 116 Collective 117 118 Input Parameter: 119 . map - the `PetscLayout` 120 121 Level: developer 122 123 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, 124 `PetscLayout`, `PetscLayoutCreate()`, 125 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()` 126 @*/ 127 PetscErrorCode PetscLayoutDestroy(PetscLayout *map) 128 { 129 PetscFunctionBegin; 130 if (!*map) PetscFunctionReturn(PETSC_SUCCESS); 131 if (!(*map)->refcnt--) { 132 if ((*map)->range_alloc) PetscCall(PetscFree((*map)->range)); 133 PetscCall(ISLocalToGlobalMappingDestroy(&(*map)->mapping)); 134 PetscCall(PetscFree(*map)); 135 } 136 *map = NULL; 137 PetscFunctionReturn(PETSC_SUCCESS); 138 } 139 140 /*@ 141 PetscLayoutCreateFromRanges - Creates a new `PetscLayout` with the given ownership ranges and sets it up. 142 143 Collective 144 145 Input Parameters: 146 + comm - the MPI communicator 147 . range - the array of ownership ranges for each rank with length commsize+1 148 . mode - the copy mode for range 149 - bs - the block size (or `PETSC_DECIDE`) 150 151 Output Parameter: 152 . newmap - the new `PetscLayout` 153 154 Level: developer 155 156 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, 157 `PetscLayoutGetLocalSize()`, `PetscLayout`, `PetscLayoutDestroy()`, 158 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`, `PetscLayoutCreateFromSizes()` 159 @*/ 160 PetscErrorCode PetscLayoutCreateFromRanges(MPI_Comm comm, const PetscInt range[], PetscCopyMode mode, PetscInt bs, PetscLayout *newmap) 161 { 162 PetscLayout map; 163 PetscMPIInt rank; 164 165 PetscFunctionBegin; 166 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 167 PetscCall(PetscLayoutCreate(comm, &map)); 168 PetscCall(PetscLayoutSetBlockSize(map, bs)); 169 switch (mode) { 170 case PETSC_COPY_VALUES: 171 PetscCall(PetscMalloc1(map->size + 1, &map->range)); 172 PetscCall(PetscArraycpy(map->range, range, map->size + 1)); 173 break; 174 case PETSC_USE_POINTER: 175 map->range_alloc = PETSC_FALSE; 176 break; 177 default: 178 map->range = (PetscInt *)range; 179 break; 180 } 181 map->rstart = map->range[rank]; 182 map->rend = map->range[rank + 1]; 183 map->n = map->rend - map->rstart; 184 map->N = map->range[map->size]; 185 if (PetscDefined(USE_DEBUG)) { /* just check that n, N and bs are consistent */ 186 PetscInt tmp; 187 PetscCallMPI(MPIU_Allreduce(&map->n, &tmp, 1, MPIU_INT, MPI_SUM, map->comm)); 188 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 ". The provided PetscLayout is wrong.", tmp, map->N, map->n); 189 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); 190 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); 191 } 192 /* lock the layout */ 193 map->setupcalled = PETSC_TRUE; 194 map->oldn = map->n; 195 map->oldN = map->N; 196 map->oldbs = map->bs; 197 *newmap = map; 198 PetscFunctionReturn(PETSC_SUCCESS); 199 } 200 201 /*@ 202 PetscLayoutSetUp - given a map where you have set either the global or local 203 size sets up the map so that it may be used. 204 205 Collective 206 207 Input Parameter: 208 . map - pointer to the map 209 210 Level: developer 211 212 Notes: 213 Typical calling sequence 214 .vb 215 PetscLayoutCreate(MPI_Comm,PetscLayout *); 216 PetscLayoutSetBlockSize(PetscLayout,1); 217 PetscLayoutSetSize(PetscLayout,n) or PetscLayoutSetLocalSize(PetscLayout,N); or both 218 PetscLayoutSetUp(PetscLayout); 219 PetscLayoutGetSize(PetscLayout,PetscInt *); 220 .ve 221 222 If range exists, and local size is not set, everything gets computed from the range. 223 224 If the local size, global size are already set and range exists then this does nothing. 225 226 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, 227 `PetscLayout`, `PetscLayoutDestroy()`, 228 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutCreate()`, `PetscSplitOwnership()` 229 @*/ 230 PetscErrorCode PetscLayoutSetUp(PetscLayout map) 231 { 232 PetscMPIInt rank; 233 PetscInt p; 234 235 PetscFunctionBegin; 236 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 ")", 237 map->oldn, map->oldN, map->n, map->N); 238 if (map->setupcalled) PetscFunctionReturn(PETSC_SUCCESS); 239 240 PetscCheck(map->n < 0 || 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); 241 PetscCheck(map->N < 0 || 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); 242 243 PetscCallMPI(MPI_Comm_rank(map->comm, &rank)); 244 if (map->n > 0) map->n = map->n / map->bs; 245 if (map->N > 0) map->N = map->N / map->bs; 246 PetscCall(PetscSplitOwnership(map->comm, &map->n, &map->N)); 247 map->n = map->n * map->bs; 248 map->N = map->N * map->bs; 249 if (!map->range) PetscCall(PetscMalloc1(map->size + 1, &map->range)); 250 PetscCallMPI(MPI_Allgather(&map->n, 1, MPIU_INT, map->range + 1, 1, MPIU_INT, map->comm)); 251 252 map->range[0] = 0; 253 for (p = 2; p <= map->size; p++) map->range[p] += map->range[p - 1]; 254 255 map->rstart = map->range[rank]; 256 map->rend = map->range[rank + 1]; 257 258 /* lock the layout */ 259 map->setupcalled = PETSC_TRUE; 260 map->oldn = map->n; 261 map->oldN = map->N; 262 map->oldbs = map->bs; 263 PetscFunctionReturn(PETSC_SUCCESS); 264 } 265 266 /*@ 267 PetscLayoutDuplicate - creates a new `PetscLayout` with the same information as a given one. If the `PetscLayout` already exists it is destroyed first. 268 269 Collective 270 271 Input Parameter: 272 . in - input `PetscLayout` to be duplicated 273 274 Output Parameter: 275 . out - the copy 276 277 Level: developer 278 279 Note: 280 `PetscLayoutSetUp()` does not need to be called on the resulting `PetscLayout` 281 282 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutReference()` 283 @*/ 284 PetscErrorCode PetscLayoutDuplicate(PetscLayout in, PetscLayout *out) 285 { 286 MPI_Comm comm = in->comm; 287 288 PetscFunctionBegin; 289 PetscCall(PetscLayoutDestroy(out)); 290 PetscCall(PetscLayoutCreate(comm, out)); 291 PetscCall(PetscMemcpy(*out, in, sizeof(struct _n_PetscLayout))); 292 if (in->range) { 293 PetscCall(PetscMalloc1((*out)->size + 1, &(*out)->range)); 294 PetscCall(PetscArraycpy((*out)->range, in->range, (*out)->size + 1)); 295 } 296 (*out)->refcnt = 0; 297 PetscFunctionReturn(PETSC_SUCCESS); 298 } 299 300 /*@ 301 PetscLayoutReference - Causes a PETSc `Vec` or `Mat` to share a `PetscLayout` with one that already exists. 302 303 Collective 304 305 Input Parameter: 306 . in - input `PetscLayout` to be copied 307 308 Output Parameter: 309 . out - the reference location 310 311 Level: developer 312 313 Notes: 314 `PetscLayoutSetUp()` does not need to be called on the resulting `PetscLayout` 315 316 If the out location already contains a `PetscLayout` it is destroyed 317 318 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutDuplicate()` 319 @*/ 320 PetscErrorCode PetscLayoutReference(PetscLayout in, PetscLayout *out) 321 { 322 PetscFunctionBegin; 323 in->refcnt++; 324 PetscCall(PetscLayoutDestroy(out)); 325 *out = in; 326 PetscFunctionReturn(PETSC_SUCCESS); 327 } 328 329 /*@ 330 PetscLayoutSetISLocalToGlobalMapping - sets a `ISLocalGlobalMapping` into a `PetscLayout` 331 332 Collective 333 334 Input Parameters: 335 + in - input `PetscLayout` 336 - ltog - the local to global mapping 337 338 Level: developer 339 340 Notes: 341 `PetscLayoutSetUp()` does not need to be called on the resulting `PetscLayout` 342 343 If the `PetscLayout` already contains a `ISLocalGlobalMapping` it is destroyed 344 345 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutDuplicate()` 346 @*/ 347 PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in, ISLocalToGlobalMapping ltog) 348 { 349 PetscFunctionBegin; 350 if (ltog) { 351 PetscInt bs; 352 353 PetscCall(ISLocalToGlobalMappingGetBlockSize(ltog, &bs)); 354 PetscCheck(in->bs == 1 || 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); 355 } 356 PetscCall(PetscObjectReference((PetscObject)ltog)); 357 PetscCall(ISLocalToGlobalMappingDestroy(&in->mapping)); 358 in->mapping = ltog; 359 PetscFunctionReturn(PETSC_SUCCESS); 360 } 361 362 /*@ 363 PetscLayoutSetLocalSize - Sets the local size for a `PetscLayout` object. 364 365 Collective 366 367 Input Parameters: 368 + map - pointer to the map 369 - n - the local size, pass `PETSC_DECIDE` (the default) to have this value determined by the global size set with `PetscLayoutSetSize()` 370 371 Level: developer 372 373 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetUp()` 374 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()` 375 @*/ 376 PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map, PetscInt n) 377 { 378 PetscFunctionBegin; 379 PetscCheck(n % map->bs == 0, map->comm, PETSC_ERR_ARG_INCOMP, "Local size %" PetscInt_FMT " not compatible with block size %" PetscInt_FMT, n, map->bs); 380 map->n = n; 381 PetscFunctionReturn(PETSC_SUCCESS); 382 } 383 384 /*@ 385 PetscLayoutGetLocalSize - Gets the local size for a `PetscLayout` object. 386 387 Not Collective 388 389 Input Parameter: 390 . map - pointer to the map 391 392 Output Parameter: 393 . n - the local size 394 395 Level: developer 396 397 Note: 398 Call this after the call to `PetscLayoutSetUp()` 399 400 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()` 401 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()` 402 @*/ 403 PetscErrorCode PetscLayoutGetLocalSize(PetscLayout map, PetscInt *n) 404 { 405 PetscFunctionBegin; 406 *n = map->n; 407 PetscFunctionReturn(PETSC_SUCCESS); 408 } 409 410 /*@ 411 PetscLayoutSetSize - Sets the global size for a `PetscLayout` object. 412 413 Logically Collective 414 415 Input Parameters: 416 + map - pointer to the map 417 - n - the global size, use `PETSC_DETERMINE` (the default) to have this value computed as the sum of the local sizes set with `PetscLayoutSetLocalSize()` 418 419 Level: developer 420 421 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()` 422 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()` 423 @*/ 424 PetscErrorCode PetscLayoutSetSize(PetscLayout map, PetscInt n) 425 { 426 PetscFunctionBegin; 427 map->N = n; 428 PetscFunctionReturn(PETSC_SUCCESS); 429 } 430 431 /*@ 432 PetscLayoutGetSize - Gets the global size for a `PetscLayout` object. 433 434 Not Collective 435 436 Input Parameter: 437 . map - pointer to the map 438 439 Output Parameter: 440 . n - the global size 441 442 Level: developer 443 444 Note: 445 Call this after the call to `PetscLayoutSetUp()` 446 447 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutSetUp()` 448 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()` 449 @*/ 450 PetscErrorCode PetscLayoutGetSize(PetscLayout map, PetscInt *n) 451 { 452 PetscFunctionBegin; 453 *n = map->N; 454 PetscFunctionReturn(PETSC_SUCCESS); 455 } 456 457 /*@ 458 PetscLayoutSetBlockSize - Sets the block size for a `PetscLayout` object. 459 460 Logically Collective 461 462 Input Parameters: 463 + map - pointer to the map 464 - bs - the size 465 466 Level: developer 467 468 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetBlockSize()`, 469 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()` 470 @*/ 471 PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map, PetscInt bs) 472 { 473 PetscFunctionBegin; 474 PetscCheck(bs > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Block size %" PetscInt_FMT " must be positive", bs); 475 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); 476 if (map->mapping) { 477 PetscInt obs; 478 479 PetscCall(ISLocalToGlobalMappingGetBlockSize(map->mapping, &obs)); 480 if (obs > 1) PetscCall(ISLocalToGlobalMappingSetBlockSize(map->mapping, bs)); 481 } 482 map->bs = bs; 483 PetscFunctionReturn(PETSC_SUCCESS); 484 } 485 486 /*@ 487 PetscLayoutGetBlockSize - Gets the block size for a `PetscLayout` object. 488 489 Not Collective 490 491 Input Parameter: 492 . map - pointer to the map 493 494 Output Parameter: 495 . bs - the size 496 497 Level: developer 498 499 Notes: 500 Call this after the call to `PetscLayoutSetUp()` 501 502 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutSetUp()` 503 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetSize()` 504 @*/ 505 PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map, PetscInt *bs) 506 { 507 PetscFunctionBegin; 508 *bs = map->bs; 509 PetscFunctionReturn(PETSC_SUCCESS); 510 } 511 512 /*@ 513 PetscLayoutGetRange - gets the range of values owned by this process 514 515 Not Collective 516 517 Input Parameter: 518 . map - pointer to the map 519 520 Output Parameters: 521 + rstart - first index owned by this process 522 - rend - one more than the last index owned by this process 523 524 Level: developer 525 526 Note: 527 Call this after the call to `PetscLayoutSetUp()` 528 529 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`, 530 `PetscLayoutGetSize()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutSetUp()` 531 @*/ 532 PetscErrorCode PetscLayoutGetRange(PetscLayout map, PetscInt *rstart, PetscInt *rend) 533 { 534 PetscFunctionBegin; 535 if (rstart) *rstart = map->rstart; 536 if (rend) *rend = map->rend; 537 PetscFunctionReturn(PETSC_SUCCESS); 538 } 539 540 /*@C 541 PetscLayoutGetRanges - gets the ranges of values owned by all processes 542 543 Not Collective 544 545 Input Parameter: 546 . map - pointer to the map 547 548 Output Parameter: 549 . range - start of each processors range of indices (the final entry is one more than the 550 last index on the last process). The length of the array is one more than the number of processes in the MPI 551 communicator owned by `map` 552 553 Level: developer 554 555 Note: 556 Call this after the call to `PetscLayoutSetUp()` 557 558 Fortran Notes: 559 .vb 560 PetscInt, pointer :: range(:) 561 .ve 562 563 Call `PetscLayoutRestoreRanges()` when no longer needed. 564 565 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`, 566 `PetscLayoutGetSize()`, `PetscLayoutGetRange()`, `PetscLayoutSetBlockSize()`, `PetscLayoutSetUp()` 567 @*/ 568 PetscErrorCode PetscLayoutGetRanges(PetscLayout map, const PetscInt *range[]) 569 { 570 PetscFunctionBegin; 571 *range = map->range; 572 PetscFunctionReturn(PETSC_SUCCESS); 573 } 574 575 /*@ 576 PetscLayoutCompare - Compares two layouts 577 578 Not Collective 579 580 Input Parameters: 581 + mapa - pointer to the first map 582 - mapb - pointer to the second map 583 584 Output Parameter: 585 . congruent - `PETSC_TRUE` if the two layouts are congruent, `PETSC_FALSE` otherwise 586 587 Level: beginner 588 589 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetBlockSize()`, 590 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()` 591 @*/ 592 PetscErrorCode PetscLayoutCompare(PetscLayout mapa, PetscLayout mapb, PetscBool *congruent) 593 { 594 PetscFunctionBegin; 595 *congruent = PETSC_FALSE; 596 if (mapa->N == mapb->N && mapa->range && mapb->range && mapa->size == mapb->size) PetscCall(PetscArraycmp(mapa->range, mapb->range, mapa->size + 1, congruent)); 597 PetscFunctionReturn(PETSC_SUCCESS); 598 } 599 600 /*@ 601 PetscLayoutFindOwner - Find the owning MPI process for a global index 602 603 Not Collective; No Fortran Support 604 605 Input Parameters: 606 + map - the layout 607 - idx - global index to find the owner of 608 609 Output Parameter: 610 . owner - the owning rank 611 612 Level: developer 613 614 .seealso: `PetscLayout`, `PetscLayoutFindOwnerIndex()` 615 @*/ 616 PetscErrorCode PetscLayoutFindOwner(PetscLayout map, PetscInt idx, PetscMPIInt *owner) 617 { 618 PetscMPIInt lo = 0, hi, t; 619 620 PetscFunctionBegin; 621 *owner = -1; /* GCC erroneously issues warning about possibly uninitialized use when error condition */ 622 PetscAssert((map->n >= 0) && (map->N >= 0) && (map->range), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "PetscLayoutSetUp() must be called first"); 623 PetscAssert(idx >= 0 && idx <= map->N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Index %" PetscInt_FMT " is out of range", idx); 624 hi = map->size; 625 while (hi - lo > 1) { 626 t = lo + (hi - lo) / 2; 627 if (idx < map->range[t]) hi = t; 628 else lo = t; 629 } 630 *owner = lo; 631 PetscFunctionReturn(PETSC_SUCCESS); 632 } 633 634 /*@ 635 PetscLayoutFindOwnerIndex - Find the owning MPI process and the local index on that process for a global index 636 637 Not Collective; No Fortran Support 638 639 Input Parameters: 640 + map - the layout 641 - idx - global index to find the owner of 642 643 Output Parameters: 644 + owner - the owning rank 645 - lidx - local index used by the owner for `idx` 646 647 Level: developer 648 649 .seealso: `PetscLayout`, `PetscLayoutFindOwner()` 650 @*/ 651 PetscErrorCode PetscLayoutFindOwnerIndex(PetscLayout map, PetscInt idx, PetscMPIInt *owner, PetscInt *lidx) 652 { 653 PetscMPIInt lo = 0, hi, t; 654 655 PetscFunctionBegin; 656 PetscAssert((map->n >= 0) && (map->N >= 0) && (map->range), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "PetscLayoutSetUp() must be called first"); 657 PetscAssert(idx >= 0 && idx <= map->N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Index %" PetscInt_FMT " is out of range", idx); 658 hi = map->size; 659 while (hi - lo > 1) { 660 t = lo + (hi - lo) / 2; 661 if (idx < map->range[t]) hi = t; 662 else lo = t; 663 } 664 if (owner) *owner = lo; 665 if (lidx) *lidx = idx - map->range[lo]; 666 PetscFunctionReturn(PETSC_SUCCESS); 667 } 668