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