1 #include <petsc/private/isimpl.h> /*I "petscis.h" I*/ 2 #include <petsc/private/hashmapi.h> 3 #include <petscsf.h> 4 #include <petscviewer.h> 5 #include <petscbt.h> 6 7 PetscClassId IS_LTOGM_CLASSID; 8 static PetscErrorCode ISLocalToGlobalMappingSetUpBlockInfo_Private(ISLocalToGlobalMapping); 9 10 typedef struct { 11 PetscInt *globals; 12 } ISLocalToGlobalMapping_Basic; 13 14 typedef struct { 15 PetscHMapI globalht; 16 } ISLocalToGlobalMapping_Hash; 17 18 /*@C 19 ISGetPointRange - Returns a description of the points in an `IS` suitable for traversal 20 21 Not Collective 22 23 Input Parameter: 24 . pointIS - The `IS` object 25 26 Output Parameters: 27 + pStart - The first index, see notes 28 . pEnd - One past the last index, see notes 29 - points - The indices, see notes 30 31 Level: intermediate 32 33 Notes: 34 If the `IS` contains contiguous indices in an `ISSTRIDE`, then the indices are contained in [pStart, pEnd) and points = `NULL`. 35 Otherwise, `pStart = 0`, `pEnd = numIndices`, and points is an array of the indices. This supports the following pattern 36 .vb 37 ISGetPointRange(is, &pStart, &pEnd, &points); 38 for (p = pStart; p < pEnd; ++p) { 39 const PetscInt point = points ? points[p] : p; 40 // use point 41 } 42 ISRestorePointRange(is, &pstart, &pEnd, &points); 43 .ve 44 Hence the same code can be written for `pointIS` being a `ISSTRIDE` or `ISGENERAL` 45 46 .seealso: [](sec_scatter), `IS`, `ISRestorePointRange()`, `ISGetPointSubrange()`, `ISGetIndices()`, `ISCreateStride()` 47 @*/ 48 PetscErrorCode ISGetPointRange(IS pointIS, PetscInt *pStart, PetscInt *pEnd, const PetscInt **points) 49 { 50 PetscInt numCells, step = 1; 51 PetscBool isStride; 52 53 PetscFunctionBeginHot; 54 *pStart = 0; 55 *points = NULL; 56 PetscCall(ISGetLocalSize(pointIS, &numCells)); 57 PetscCall(PetscObjectTypeCompare((PetscObject)pointIS, ISSTRIDE, &isStride)); 58 if (isStride) PetscCall(ISStrideGetInfo(pointIS, pStart, &step)); 59 *pEnd = *pStart + numCells; 60 if (!isStride || step != 1) PetscCall(ISGetIndices(pointIS, points)); 61 PetscFunctionReturn(PETSC_SUCCESS); 62 } 63 64 /*@C 65 ISRestorePointRange - Destroys the traversal description created with `ISGetPointRange()` 66 67 Not Collective 68 69 Input Parameters: 70 + pointIS - The `IS` object 71 . pStart - The first index, from `ISGetPointRange()` 72 . pEnd - One past the last index, from `ISGetPointRange()` 73 - points - The indices, from `ISGetPointRange()` 74 75 Level: intermediate 76 77 .seealso: [](sec_scatter), `IS`, `ISGetPointRange()`, `ISGetPointSubrange()`, `ISGetIndices()`, `ISCreateStride()` 78 @*/ 79 PetscErrorCode ISRestorePointRange(IS pointIS, PetscInt *pStart, PetscInt *pEnd, const PetscInt **points) 80 { 81 PetscInt step = 1; 82 PetscBool isStride; 83 84 PetscFunctionBeginHot; 85 PetscCall(PetscObjectTypeCompare((PetscObject)pointIS, ISSTRIDE, &isStride)); 86 if (isStride) PetscCall(ISStrideGetInfo(pointIS, pStart, &step)); 87 if (!isStride || step != 1) PetscCall(ISGetIndices(pointIS, points)); 88 PetscFunctionReturn(PETSC_SUCCESS); 89 } 90 91 /*@C 92 ISGetPointSubrange - Configures the input `IS` to be a subrange for the traversal information given 93 94 Not Collective 95 96 Input Parameters: 97 + subpointIS - The `IS` object to be configured 98 . pStart - The first index of the subrange 99 . pEnd - One past the last index for the subrange 100 - points - The indices for the entire range, from `ISGetPointRange()` 101 102 Output Parameters: 103 . subpointIS - The `IS` object now configured to be a subrange 104 105 Level: intermediate 106 107 Note: 108 The input `IS` will now respond properly to calls to `ISGetPointRange()` and return the subrange. 109 110 .seealso: [](sec_scatter), `IS`, `ISGetPointRange()`, `ISRestorePointRange()`, `ISGetIndices()`, `ISCreateStride()` 111 @*/ 112 PetscErrorCode ISGetPointSubrange(IS subpointIS, PetscInt pStart, PetscInt pEnd, const PetscInt *points) 113 { 114 PetscFunctionBeginHot; 115 if (points) { 116 PetscCall(ISSetType(subpointIS, ISGENERAL)); 117 PetscCall(ISGeneralSetIndices(subpointIS, pEnd - pStart, &points[pStart], PETSC_USE_POINTER)); 118 } else { 119 PetscCall(ISSetType(subpointIS, ISSTRIDE)); 120 PetscCall(ISStrideSetStride(subpointIS, pEnd - pStart, pStart, 1)); 121 } 122 PetscFunctionReturn(PETSC_SUCCESS); 123 } 124 125 /* -----------------------------------------------------------------------------------------*/ 126 127 /* 128 Creates the global mapping information in the ISLocalToGlobalMapping structure 129 130 If the user has not selected how to handle the global to local mapping then use HASH for "large" problems 131 */ 132 static PetscErrorCode ISGlobalToLocalMappingSetUp(ISLocalToGlobalMapping mapping) 133 { 134 PetscInt i, *idx = mapping->indices, n = mapping->n, end, start; 135 136 PetscFunctionBegin; 137 if (mapping->data) PetscFunctionReturn(PETSC_SUCCESS); 138 end = 0; 139 start = PETSC_MAX_INT; 140 141 for (i = 0; i < n; i++) { 142 if (idx[i] < 0) continue; 143 if (idx[i] < start) start = idx[i]; 144 if (idx[i] > end) end = idx[i]; 145 } 146 if (start > end) { 147 start = 0; 148 end = -1; 149 } 150 mapping->globalstart = start; 151 mapping->globalend = end; 152 if (!((PetscObject)mapping)->type_name) { 153 if ((end - start) > PetscMax(4 * n, 1000000)) { 154 PetscCall(ISLocalToGlobalMappingSetType(mapping, ISLOCALTOGLOBALMAPPINGHASH)); 155 } else { 156 PetscCall(ISLocalToGlobalMappingSetType(mapping, ISLOCALTOGLOBALMAPPINGBASIC)); 157 } 158 } 159 PetscTryTypeMethod(mapping, globaltolocalmappingsetup); 160 PetscFunctionReturn(PETSC_SUCCESS); 161 } 162 163 static PetscErrorCode ISGlobalToLocalMappingSetUp_Basic(ISLocalToGlobalMapping mapping) 164 { 165 PetscInt i, *idx = mapping->indices, n = mapping->n, end, start, *globals; 166 ISLocalToGlobalMapping_Basic *map; 167 168 PetscFunctionBegin; 169 start = mapping->globalstart; 170 end = mapping->globalend; 171 PetscCall(PetscNew(&map)); 172 PetscCall(PetscMalloc1(end - start + 2, &globals)); 173 map->globals = globals; 174 for (i = 0; i < end - start + 1; i++) globals[i] = -1; 175 for (i = 0; i < n; i++) { 176 if (idx[i] < 0) continue; 177 globals[idx[i] - start] = i; 178 } 179 mapping->data = (void *)map; 180 PetscFunctionReturn(PETSC_SUCCESS); 181 } 182 183 static PetscErrorCode ISGlobalToLocalMappingSetUp_Hash(ISLocalToGlobalMapping mapping) 184 { 185 PetscInt i, *idx = mapping->indices, n = mapping->n; 186 ISLocalToGlobalMapping_Hash *map; 187 188 PetscFunctionBegin; 189 PetscCall(PetscNew(&map)); 190 PetscCall(PetscHMapICreate(&map->globalht)); 191 for (i = 0; i < n; i++) { 192 if (idx[i] < 0) continue; 193 PetscCall(PetscHMapISet(map->globalht, idx[i], i)); 194 } 195 mapping->data = (void *)map; 196 PetscFunctionReturn(PETSC_SUCCESS); 197 } 198 199 static PetscErrorCode ISLocalToGlobalMappingDestroy_Basic(ISLocalToGlobalMapping mapping) 200 { 201 ISLocalToGlobalMapping_Basic *map = (ISLocalToGlobalMapping_Basic *)mapping->data; 202 203 PetscFunctionBegin; 204 if (!map) PetscFunctionReturn(PETSC_SUCCESS); 205 PetscCall(PetscFree(map->globals)); 206 PetscCall(PetscFree(mapping->data)); 207 PetscFunctionReturn(PETSC_SUCCESS); 208 } 209 210 static PetscErrorCode ISLocalToGlobalMappingDestroy_Hash(ISLocalToGlobalMapping mapping) 211 { 212 ISLocalToGlobalMapping_Hash *map = (ISLocalToGlobalMapping_Hash *)mapping->data; 213 214 PetscFunctionBegin; 215 if (!map) PetscFunctionReturn(PETSC_SUCCESS); 216 PetscCall(PetscHMapIDestroy(&map->globalht)); 217 PetscCall(PetscFree(mapping->data)); 218 PetscFunctionReturn(PETSC_SUCCESS); 219 } 220 221 #define GTOLTYPE _Basic 222 #define GTOLNAME _Basic 223 #define GTOLBS mapping->bs 224 #define GTOL(g, local) \ 225 do { \ 226 local = map->globals[g / bs - start]; \ 227 if (local >= 0) local = bs * local + (g % bs); \ 228 } while (0) 229 230 #include <../src/vec/is/utils/isltog.h> 231 232 #define GTOLTYPE _Basic 233 #define GTOLNAME Block_Basic 234 #define GTOLBS 1 235 #define GTOL(g, local) \ 236 do { \ 237 local = map->globals[g - start]; \ 238 } while (0) 239 #include <../src/vec/is/utils/isltog.h> 240 241 #define GTOLTYPE _Hash 242 #define GTOLNAME _Hash 243 #define GTOLBS mapping->bs 244 #define GTOL(g, local) \ 245 do { \ 246 (void)PetscHMapIGet(map->globalht, g / bs, &local); \ 247 if (local >= 0) local = bs * local + (g % bs); \ 248 } while (0) 249 #include <../src/vec/is/utils/isltog.h> 250 251 #define GTOLTYPE _Hash 252 #define GTOLNAME Block_Hash 253 #define GTOLBS 1 254 #define GTOL(g, local) \ 255 do { \ 256 (void)PetscHMapIGet(map->globalht, g, &local); \ 257 } while (0) 258 #include <../src/vec/is/utils/isltog.h> 259 260 /*@ 261 ISLocalToGlobalMappingDuplicate - Duplicates the local to global mapping object 262 263 Not Collective 264 265 Input Parameter: 266 . ltog - local to global mapping 267 268 Output Parameter: 269 . nltog - the duplicated local to global mapping 270 271 Level: advanced 272 273 .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreate()` 274 @*/ 275 PetscErrorCode ISLocalToGlobalMappingDuplicate(ISLocalToGlobalMapping ltog, ISLocalToGlobalMapping *nltog) 276 { 277 ISLocalToGlobalMappingType l2gtype; 278 279 PetscFunctionBegin; 280 PetscValidHeaderSpecific(ltog, IS_LTOGM_CLASSID, 1); 281 PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)ltog), ltog->bs, ltog->n, ltog->indices, PETSC_COPY_VALUES, nltog)); 282 PetscCall(ISLocalToGlobalMappingGetType(ltog, &l2gtype)); 283 PetscCall(ISLocalToGlobalMappingSetType(*nltog, l2gtype)); 284 PetscFunctionReturn(PETSC_SUCCESS); 285 } 286 287 /*@ 288 ISLocalToGlobalMappingGetSize - Gets the local size of a local to global mapping 289 290 Not Collective 291 292 Input Parameter: 293 . mapping - local to global mapping 294 295 Output Parameter: 296 . n - the number of entries in the local mapping, `ISLocalToGlobalMappingGetIndices()` returns an array of this length 297 298 Level: advanced 299 300 .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreate()` 301 @*/ 302 PetscErrorCode ISLocalToGlobalMappingGetSize(ISLocalToGlobalMapping mapping, PetscInt *n) 303 { 304 PetscFunctionBegin; 305 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1); 306 PetscAssertPointer(n, 2); 307 *n = mapping->bs * mapping->n; 308 PetscFunctionReturn(PETSC_SUCCESS); 309 } 310 311 /*@C 312 ISLocalToGlobalMappingViewFromOptions - View an `ISLocalToGlobalMapping` based on values in the options database 313 314 Collective 315 316 Input Parameters: 317 + A - the local to global mapping object 318 . obj - Optional object that provides the options prefix used for the options database query 319 - name - command line option 320 321 Level: intermediate 322 323 Note: 324 See `PetscObjectViewFromOptions()` for the available `PetscViewer` and `PetscViewerFormat` 325 326 .seealso: [](sec_scatter), `PetscViewer`, ``ISLocalToGlobalMapping`, `ISLocalToGlobalMappingView`, `PetscObjectViewFromOptions()`, `ISLocalToGlobalMappingCreate()` 327 @*/ 328 PetscErrorCode ISLocalToGlobalMappingViewFromOptions(ISLocalToGlobalMapping A, PetscObject obj, const char name[]) 329 { 330 PetscFunctionBegin; 331 PetscValidHeaderSpecific(A, IS_LTOGM_CLASSID, 1); 332 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 333 PetscFunctionReturn(PETSC_SUCCESS); 334 } 335 336 /*@C 337 ISLocalToGlobalMappingView - View a local to global mapping 338 339 Not Collective 340 341 Input Parameters: 342 + mapping - local to global mapping 343 - viewer - viewer 344 345 Level: advanced 346 347 .seealso: [](sec_scatter), `PetscViewer`, `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreate()` 348 @*/ 349 PetscErrorCode ISLocalToGlobalMappingView(ISLocalToGlobalMapping mapping, PetscViewer viewer) 350 { 351 PetscInt i; 352 PetscMPIInt rank; 353 PetscBool iascii; 354 355 PetscFunctionBegin; 356 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1); 357 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mapping), &viewer)); 358 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 359 360 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)mapping), &rank)); 361 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 362 if (iascii) { 363 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mapping, viewer)); 364 PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 365 for (i = 0; i < mapping->n; i++) { 366 PetscInt bs = mapping->bs, g = mapping->indices[i]; 367 if (bs == 1) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %" PetscInt_FMT " %" PetscInt_FMT "\n", rank, i, g)); 368 else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %" PetscInt_FMT ":%" PetscInt_FMT " %" PetscInt_FMT ":%" PetscInt_FMT "\n", rank, i * bs, (i + 1) * bs, g * bs, (g + 1) * bs)); 369 } 370 PetscCall(PetscViewerFlush(viewer)); 371 PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 372 } 373 PetscFunctionReturn(PETSC_SUCCESS); 374 } 375 376 /*@ 377 ISLocalToGlobalMappingCreateIS - Creates a mapping between a local (0 to n) 378 ordering and a global parallel ordering. 379 380 Not Collective 381 382 Input Parameter: 383 . is - index set containing the global numbers for each local number 384 385 Output Parameter: 386 . mapping - new mapping data structure 387 388 Level: advanced 389 390 Note: 391 the block size of the `IS` determines the block size of the mapping 392 393 .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingSetFromOptions()` 394 @*/ 395 PetscErrorCode ISLocalToGlobalMappingCreateIS(IS is, ISLocalToGlobalMapping *mapping) 396 { 397 PetscInt n, bs; 398 const PetscInt *indices; 399 MPI_Comm comm; 400 PetscBool isblock; 401 402 PetscFunctionBegin; 403 PetscValidHeaderSpecific(is, IS_CLASSID, 1); 404 PetscAssertPointer(mapping, 2); 405 406 PetscCall(PetscObjectGetComm((PetscObject)is, &comm)); 407 PetscCall(ISGetLocalSize(is, &n)); 408 PetscCall(PetscObjectTypeCompare((PetscObject)is, ISBLOCK, &isblock)); 409 if (!isblock) { 410 PetscCall(ISGetIndices(is, &indices)); 411 PetscCall(ISLocalToGlobalMappingCreate(comm, 1, n, indices, PETSC_COPY_VALUES, mapping)); 412 PetscCall(ISRestoreIndices(is, &indices)); 413 } else { 414 PetscCall(ISGetBlockSize(is, &bs)); 415 PetscCall(ISBlockGetIndices(is, &indices)); 416 PetscCall(ISLocalToGlobalMappingCreate(comm, bs, n / bs, indices, PETSC_COPY_VALUES, mapping)); 417 PetscCall(ISBlockRestoreIndices(is, &indices)); 418 } 419 PetscFunctionReturn(PETSC_SUCCESS); 420 } 421 422 /*@C 423 ISLocalToGlobalMappingCreateSF - Creates a mapping between a local (0 to n) 424 ordering and a global parallel ordering. 425 426 Collective 427 428 Input Parameters: 429 + sf - star forest mapping contiguous local indices to (rank, offset) 430 - start - first global index on this process, or `PETSC_DECIDE` to compute contiguous global numbering automatically 431 432 Output Parameter: 433 . mapping - new mapping data structure 434 435 Level: advanced 436 437 Note: 438 If a process calls this function with `start` = `PETSC_DECIDE` then all processes must, otherwise the program will hang. 439 440 .seealso: [](sec_scatter), `PetscSF`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingSetFromOptions()` 441 @*/ 442 PetscErrorCode ISLocalToGlobalMappingCreateSF(PetscSF sf, PetscInt start, ISLocalToGlobalMapping *mapping) 443 { 444 PetscInt i, maxlocal, nroots, nleaves, *globals, *ltog; 445 MPI_Comm comm; 446 447 PetscFunctionBegin; 448 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 1); 449 PetscAssertPointer(mapping, 3); 450 PetscCall(PetscObjectGetComm((PetscObject)sf, &comm)); 451 PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, NULL, NULL)); 452 if (start == PETSC_DECIDE) { 453 start = 0; 454 PetscCallMPI(MPI_Exscan(&nroots, &start, 1, MPIU_INT, MPI_SUM, comm)); 455 } else PetscCheck(start >= 0, comm, PETSC_ERR_ARG_OUTOFRANGE, "start must be nonnegative or PETSC_DECIDE"); 456 PetscCall(PetscSFGetLeafRange(sf, NULL, &maxlocal)); 457 ++maxlocal; 458 PetscCall(PetscMalloc1(nroots, &globals)); 459 PetscCall(PetscMalloc1(maxlocal, <og)); 460 for (i = 0; i < nroots; i++) globals[i] = start + i; 461 for (i = 0; i < maxlocal; i++) ltog[i] = -1; 462 PetscCall(PetscSFBcastBegin(sf, MPIU_INT, globals, ltog, MPI_REPLACE)); 463 PetscCall(PetscSFBcastEnd(sf, MPIU_INT, globals, ltog, MPI_REPLACE)); 464 PetscCall(ISLocalToGlobalMappingCreate(comm, 1, maxlocal, ltog, PETSC_OWN_POINTER, mapping)); 465 PetscCall(PetscFree(globals)); 466 PetscFunctionReturn(PETSC_SUCCESS); 467 } 468 469 static PetscErrorCode ISLocalToGlobalMappingResetBlockInfo_Private(ISLocalToGlobalMapping mapping) 470 { 471 PetscFunctionBegin; 472 PetscCall(PetscFree(mapping->info_procs)); 473 PetscCall(PetscFree(mapping->info_numprocs)); 474 if (mapping->info_indices) { 475 for (PetscInt i = 0; i < mapping->info_nproc; i++) PetscCall(PetscFree(mapping->info_indices[i])); 476 PetscCall(PetscFree(mapping->info_indices)); 477 } 478 if (mapping->info_nodei) PetscCall(PetscFree(mapping->info_nodei[0])); 479 PetscCall(PetscFree2(mapping->info_nodec, mapping->info_nodei)); 480 PetscFunctionReturn(PETSC_SUCCESS); 481 } 482 483 /*@ 484 ISLocalToGlobalMappingSetBlockSize - Sets the blocksize of the mapping 485 486 Not Collective 487 488 Input Parameters: 489 + mapping - mapping data structure 490 - bs - the blocksize 491 492 Level: advanced 493 494 .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()` 495 @*/ 496 PetscErrorCode ISLocalToGlobalMappingSetBlockSize(ISLocalToGlobalMapping mapping, PetscInt bs) 497 { 498 PetscInt *nid; 499 const PetscInt *oid; 500 PetscInt i, cn, on, obs, nn; 501 502 PetscFunctionBegin; 503 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1); 504 PetscCheck(bs >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid block size %" PetscInt_FMT, bs); 505 if (bs == mapping->bs) PetscFunctionReturn(PETSC_SUCCESS); 506 on = mapping->n; 507 obs = mapping->bs; 508 oid = mapping->indices; 509 nn = (on * obs) / bs; 510 PetscCheck((on * obs) % bs == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Block size %" PetscInt_FMT " is inconsistent with block size %" PetscInt_FMT " and number of block indices %" PetscInt_FMT, bs, obs, on); 511 512 PetscCall(PetscMalloc1(nn, &nid)); 513 PetscCall(ISLocalToGlobalMappingGetIndices(mapping, &oid)); 514 for (i = 0; i < nn; i++) { 515 PetscInt j; 516 for (j = 0, cn = 0; j < bs - 1; j++) { 517 if (oid[i * bs + j] < 0) { 518 cn++; 519 continue; 520 } 521 PetscCheck(oid[i * bs + j] == oid[i * bs + j + 1] - 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Block sizes %" PetscInt_FMT " and %" PetscInt_FMT " are incompatible with the block indices: non consecutive indices %" PetscInt_FMT " %" PetscInt_FMT, bs, obs, oid[i * bs + j], oid[i * bs + j + 1]); 522 } 523 if (oid[i * bs + j] < 0) cn++; 524 if (cn) { 525 PetscCheck(cn == bs, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Block sizes %" PetscInt_FMT " and %" PetscInt_FMT " are incompatible with the block indices: invalid number of negative entries in block %" PetscInt_FMT, bs, obs, cn); 526 nid[i] = -1; 527 } else { 528 nid[i] = oid[i * bs] / bs; 529 } 530 } 531 PetscCall(ISLocalToGlobalMappingRestoreIndices(mapping, &oid)); 532 533 mapping->n = nn; 534 mapping->bs = bs; 535 PetscCall(PetscFree(mapping->indices)); 536 mapping->indices = nid; 537 mapping->globalstart = 0; 538 mapping->globalend = 0; 539 540 /* reset the cached information */ 541 PetscCall(ISLocalToGlobalMappingResetBlockInfo_Private(mapping)); 542 PetscTryTypeMethod(mapping, destroy); 543 PetscFunctionReturn(PETSC_SUCCESS); 544 } 545 546 /*@ 547 ISLocalToGlobalMappingGetBlockSize - Gets the blocksize of the mapping 548 ordering and a global parallel ordering. 549 550 Not Collective 551 552 Input Parameter: 553 . mapping - mapping data structure 554 555 Output Parameter: 556 . bs - the blocksize 557 558 Level: advanced 559 560 .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()` 561 @*/ 562 PetscErrorCode ISLocalToGlobalMappingGetBlockSize(ISLocalToGlobalMapping mapping, PetscInt *bs) 563 { 564 PetscFunctionBegin; 565 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1); 566 *bs = mapping->bs; 567 PetscFunctionReturn(PETSC_SUCCESS); 568 } 569 570 /*@ 571 ISLocalToGlobalMappingCreate - Creates a mapping between a local (0 to n) 572 ordering and a global parallel ordering. 573 574 Not Collective, but communicator may have more than one process 575 576 Input Parameters: 577 + comm - MPI communicator 578 . bs - the block size 579 . n - the number of local elements divided by the block size, or equivalently the number of block indices 580 . indices - the global index for each local element, these do not need to be in increasing order (sorted), these values should not be scaled (i.e. multiplied) by the blocksize bs 581 - mode - see PetscCopyMode 582 583 Output Parameter: 584 . mapping - new mapping data structure 585 586 Level: advanced 587 588 Notes: 589 There is one integer value in indices per block and it represents the actual indices bs*idx + j, where j=0,..,bs-1 590 591 For "small" problems when using `ISGlobalToLocalMappingApply()` and `ISGlobalToLocalMappingApplyBlock()`, the `ISLocalToGlobalMappingType` 592 of `ISLOCALTOGLOBALMAPPINGBASIC` will be used; this uses more memory but is faster; this approach is not scalable for extremely large mappings. 593 594 For large problems `ISLOCALTOGLOBALMAPPINGHASH` is used, this is scalable. 595 Use `ISLocalToGlobalMappingSetType()` or call `ISLocalToGlobalMappingSetFromOptions()` with the option 596 `-islocaltoglobalmapping_type` <`basic`,`hash`> to control which is used. 597 598 .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingSetFromOptions()`, 599 `ISLOCALTOGLOBALMAPPINGBASIC`, `ISLOCALTOGLOBALMAPPINGHASH` 600 `ISLocalToGlobalMappingSetType()`, `ISLocalToGlobalMappingType` 601 @*/ 602 PetscErrorCode ISLocalToGlobalMappingCreate(MPI_Comm comm, PetscInt bs, PetscInt n, const PetscInt indices[], PetscCopyMode mode, ISLocalToGlobalMapping *mapping) 603 { 604 PetscInt *in; 605 606 PetscFunctionBegin; 607 if (n) PetscAssertPointer(indices, 4); 608 PetscAssertPointer(mapping, 6); 609 610 *mapping = NULL; 611 PetscCall(ISInitializePackage()); 612 613 PetscCall(PetscHeaderCreate(*mapping, IS_LTOGM_CLASSID, "ISLocalToGlobalMapping", "Local to global mapping", "IS", comm, ISLocalToGlobalMappingDestroy, ISLocalToGlobalMappingView)); 614 (*mapping)->n = n; 615 (*mapping)->bs = bs; 616 if (mode == PETSC_COPY_VALUES) { 617 PetscCall(PetscMalloc1(n, &in)); 618 PetscCall(PetscArraycpy(in, indices, n)); 619 (*mapping)->indices = in; 620 (*mapping)->dealloc_indices = PETSC_TRUE; 621 } else if (mode == PETSC_OWN_POINTER) { 622 (*mapping)->indices = (PetscInt *)indices; 623 (*mapping)->dealloc_indices = PETSC_TRUE; 624 } else if (mode == PETSC_USE_POINTER) { 625 (*mapping)->indices = (PetscInt *)indices; 626 } else SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid mode %d", mode); 627 PetscFunctionReturn(PETSC_SUCCESS); 628 } 629 630 PetscFunctionList ISLocalToGlobalMappingList = NULL; 631 632 /*@ 633 ISLocalToGlobalMappingSetFromOptions - Set mapping options from the options database. 634 635 Not Collective 636 637 Input Parameter: 638 . mapping - mapping data structure 639 640 Options Database Key: 641 . -islocaltoglobalmapping_type - <basic,hash> nonscalable and scalable versions 642 643 Level: advanced 644 645 .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingDestroy()`, 646 `ISLocalToGlobalMappingCreateIS()`, `ISLOCALTOGLOBALMAPPINGBASIC`, 647 `ISLOCALTOGLOBALMAPPINGHASH`, `ISLocalToGlobalMappingSetType()`, `ISLocalToGlobalMappingType` 648 @*/ 649 PetscErrorCode ISLocalToGlobalMappingSetFromOptions(ISLocalToGlobalMapping mapping) 650 { 651 char type[256]; 652 ISLocalToGlobalMappingType defaulttype = "Not set"; 653 PetscBool flg; 654 655 PetscFunctionBegin; 656 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1); 657 PetscCall(ISLocalToGlobalMappingRegisterAll()); 658 PetscObjectOptionsBegin((PetscObject)mapping); 659 PetscCall(PetscOptionsFList("-islocaltoglobalmapping_type", "ISLocalToGlobalMapping method", "ISLocalToGlobalMappingSetType", ISLocalToGlobalMappingList, (char *)(((PetscObject)mapping)->type_name) ? ((PetscObject)mapping)->type_name : defaulttype, type, 256, &flg)); 660 if (flg) PetscCall(ISLocalToGlobalMappingSetType(mapping, type)); 661 PetscOptionsEnd(); 662 PetscFunctionReturn(PETSC_SUCCESS); 663 } 664 665 /*@ 666 ISLocalToGlobalMappingDestroy - Destroys a mapping between a local (0 to n) 667 ordering and a global parallel ordering. 668 669 Not Collective 670 671 Input Parameter: 672 . mapping - mapping data structure 673 674 Level: advanced 675 676 .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingCreate()` 677 @*/ 678 PetscErrorCode ISLocalToGlobalMappingDestroy(ISLocalToGlobalMapping *mapping) 679 { 680 PetscFunctionBegin; 681 if (!*mapping) PetscFunctionReturn(PETSC_SUCCESS); 682 PetscValidHeaderSpecific(*mapping, IS_LTOGM_CLASSID, 1); 683 if (--((PetscObject)*mapping)->refct > 0) { 684 *mapping = NULL; 685 PetscFunctionReturn(PETSC_SUCCESS); 686 } 687 if ((*mapping)->dealloc_indices) PetscCall(PetscFree((*mapping)->indices)); 688 PetscCall(ISLocalToGlobalMappingResetBlockInfo_Private(*mapping)); 689 PetscTryTypeMethod(*mapping, destroy); 690 PetscCall(PetscHeaderDestroy(mapping)); 691 PetscFunctionReturn(PETSC_SUCCESS); 692 } 693 694 /*@ 695 ISLocalToGlobalMappingApplyIS - Creates from an `IS` in the local numbering 696 a new index set using the global numbering defined in an `ISLocalToGlobalMapping` 697 context. 698 699 Collective 700 701 Input Parameters: 702 + mapping - mapping between local and global numbering 703 - is - index set in local numbering 704 705 Output Parameter: 706 . newis - index set in global numbering 707 708 Level: advanced 709 710 Note: 711 The output `IS` will have the same communicator as the input `IS`. 712 713 .seealso: [](sec_scatter), `ISLocalToGlobalMappingApply()`, `ISLocalToGlobalMappingCreate()`, 714 `ISLocalToGlobalMappingDestroy()`, `ISGlobalToLocalMappingApply()` 715 @*/ 716 PetscErrorCode ISLocalToGlobalMappingApplyIS(ISLocalToGlobalMapping mapping, IS is, IS *newis) 717 { 718 PetscInt n, *idxout; 719 const PetscInt *idxin; 720 721 PetscFunctionBegin; 722 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1); 723 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 724 PetscAssertPointer(newis, 3); 725 726 PetscCall(ISGetLocalSize(is, &n)); 727 PetscCall(ISGetIndices(is, &idxin)); 728 PetscCall(PetscMalloc1(n, &idxout)); 729 PetscCall(ISLocalToGlobalMappingApply(mapping, n, idxin, idxout)); 730 PetscCall(ISRestoreIndices(is, &idxin)); 731 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)is), n, idxout, PETSC_OWN_POINTER, newis)); 732 PetscFunctionReturn(PETSC_SUCCESS); 733 } 734 735 /*@ 736 ISLocalToGlobalMappingApply - Takes a list of integers in a local numbering 737 and converts them to the global numbering. 738 739 Not Collective 740 741 Input Parameters: 742 + mapping - the local to global mapping context 743 . N - number of integers 744 - in - input indices in local numbering 745 746 Output Parameter: 747 . out - indices in global numbering 748 749 Level: advanced 750 751 Note: 752 The `in` and `out` array parameters may be identical. 753 754 .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingApplyBlock()`, `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingDestroy()`, 755 `ISLocalToGlobalMappingApplyIS()`, `AOCreateBasic()`, `AOApplicationToPetsc()`, 756 `AOPetscToApplication()`, `ISGlobalToLocalMappingApply()` 757 @*/ 758 PetscErrorCode ISLocalToGlobalMappingApply(ISLocalToGlobalMapping mapping, PetscInt N, const PetscInt in[], PetscInt out[]) 759 { 760 PetscInt i, bs, Nmax; 761 762 PetscFunctionBegin; 763 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1); 764 bs = mapping->bs; 765 Nmax = bs * mapping->n; 766 if (bs == 1) { 767 const PetscInt *idx = mapping->indices; 768 for (i = 0; i < N; i++) { 769 if (in[i] < 0) { 770 out[i] = in[i]; 771 continue; 772 } 773 PetscCheck(in[i] < Nmax, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Local index %" PetscInt_FMT " too large %" PetscInt_FMT " (max) at %" PetscInt_FMT, in[i], Nmax - 1, i); 774 out[i] = idx[in[i]]; 775 } 776 } else { 777 const PetscInt *idx = mapping->indices; 778 for (i = 0; i < N; i++) { 779 if (in[i] < 0) { 780 out[i] = in[i]; 781 continue; 782 } 783 PetscCheck(in[i] < Nmax, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Local index %" PetscInt_FMT " too large %" PetscInt_FMT " (max) at %" PetscInt_FMT, in[i], Nmax - 1, i); 784 out[i] = idx[in[i] / bs] * bs + (in[i] % bs); 785 } 786 } 787 PetscFunctionReturn(PETSC_SUCCESS); 788 } 789 790 /*@ 791 ISLocalToGlobalMappingApplyBlock - Takes a list of integers in a local block numbering and converts them to the global block numbering 792 793 Not Collective 794 795 Input Parameters: 796 + mapping - the local to global mapping context 797 . N - number of integers 798 - in - input indices in local block numbering 799 800 Output Parameter: 801 . out - indices in global block numbering 802 803 Example: 804 If the index values are {0,1,6,7} set with a call to `ISLocalToGlobalMappingCreate`(`PETSC_COMM_SELF`,2,2,{0,3}) then the mapping applied to 0 805 (the first block) would produce 0 and the mapping applied to 1 (the second block) would produce 3. 806 807 Level: advanced 808 809 Note: 810 The `in` and `out` array parameters may be identical. 811 812 .seealso: [](sec_scatter), `ISLocalToGlobalMappingApply()`, `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingDestroy()`, 813 `ISLocalToGlobalMappingApplyIS()`, `AOCreateBasic()`, `AOApplicationToPetsc()`, 814 `AOPetscToApplication()`, `ISGlobalToLocalMappingApply()` 815 @*/ 816 PetscErrorCode ISLocalToGlobalMappingApplyBlock(ISLocalToGlobalMapping mapping, PetscInt N, const PetscInt in[], PetscInt out[]) 817 { 818 PetscInt i, Nmax; 819 const PetscInt *idx; 820 821 PetscFunctionBegin; 822 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1); 823 Nmax = mapping->n; 824 idx = mapping->indices; 825 for (i = 0; i < N; i++) { 826 if (in[i] < 0) { 827 out[i] = in[i]; 828 continue; 829 } 830 PetscCheck(in[i] < Nmax, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Local block index %" PetscInt_FMT " too large %" PetscInt_FMT " (max) at %" PetscInt_FMT, in[i], Nmax - 1, i); 831 out[i] = idx[in[i]]; 832 } 833 PetscFunctionReturn(PETSC_SUCCESS); 834 } 835 836 /*@ 837 ISGlobalToLocalMappingApply - Provides the local numbering for a list of integers 838 specified with a global numbering. 839 840 Not Collective 841 842 Input Parameters: 843 + mapping - mapping between local and global numbering 844 . type - `IS_GTOLM_MASK` - maps global indices with no local value to -1 in the output list (i.e., mask them) 845 `IS_GTOLM_DROP` - drops the indices with no local value from the output list 846 . n - number of global indices to map 847 - idx - global indices to map 848 849 Output Parameters: 850 + nout - number of indices in output array (if type == `IS_GTOLM_MASK` then nout = n) 851 - idxout - local index of each global index, one must pass in an array long enough 852 to hold all the indices. You can call `ISGlobalToLocalMappingApply()` with 853 idxout == NULL to determine the required length (returned in nout) 854 and then allocate the required space and call `ISGlobalToLocalMappingApply()` 855 a second time to set the values. 856 857 Level: advanced 858 859 Notes: 860 Either `nout` or `idxout` may be `NULL`. `idx` and `idxout` may be identical. 861 862 For "small" problems when using `ISGlobalToLocalMappingApply()` and `ISGlobalToLocalMappingApplyBlock()`, the `ISLocalToGlobalMappingType` of 863 `ISLOCALTOGLOBALMAPPINGBASIC` will be used; 864 this uses more memory but is faster; this approach is not scalable for extremely large mappings. For large problems `ISLOCALTOGLOBALMAPPINGHASH` is used, this is scalable. 865 Use `ISLocalToGlobalMappingSetType()` or call `ISLocalToGlobalMappingSetFromOptions()` with the option -islocaltoglobalmapping_type <basic,hash> to control which is used. 866 867 Developer Notes: 868 The manual page states that `idx` and `idxout` may be identical but the calling 869 sequence declares `idx` as const so it cannot be the same as `idxout`. 870 871 .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingApply()`, `ISGlobalToLocalMappingApplyBlock()`, `ISLocalToGlobalMappingCreate()`, 872 `ISLocalToGlobalMappingDestroy()` 873 @*/ 874 PetscErrorCode ISGlobalToLocalMappingApply(ISLocalToGlobalMapping mapping, ISGlobalToLocalMappingMode type, PetscInt n, const PetscInt idx[], PetscInt *nout, PetscInt idxout[]) 875 { 876 PetscFunctionBegin; 877 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1); 878 if (!mapping->data) PetscCall(ISGlobalToLocalMappingSetUp(mapping)); 879 PetscUseTypeMethod(mapping, globaltolocalmappingapply, type, n, idx, nout, idxout); 880 PetscFunctionReturn(PETSC_SUCCESS); 881 } 882 883 /*@ 884 ISGlobalToLocalMappingApplyIS - Creates from an `IS` in the global numbering 885 a new index set using the local numbering defined in an `ISLocalToGlobalMapping` 886 context. 887 888 Not Collective 889 890 Input Parameters: 891 + mapping - mapping between local and global numbering 892 . type - `IS_GTOLM_MASK` - maps global indices with no local value to -1 in the output list (i.e., mask them) 893 `IS_GTOLM_DROP` - drops the indices with no local value from the output list 894 - is - index set in global numbering 895 896 Output Parameter: 897 . newis - index set in local numbering 898 899 Level: advanced 900 901 Note: 902 The output `IS` will be sequential, as it encodes a purely local operation 903 904 .seealso: [](sec_scatter), `ISGlobalToLocalMapping`, `ISGlobalToLocalMappingApply()`, `ISLocalToGlobalMappingCreate()`, 905 `ISLocalToGlobalMappingDestroy()` 906 @*/ 907 PetscErrorCode ISGlobalToLocalMappingApplyIS(ISLocalToGlobalMapping mapping, ISGlobalToLocalMappingMode type, IS is, IS *newis) 908 { 909 PetscInt n, nout, *idxout; 910 const PetscInt *idxin; 911 912 PetscFunctionBegin; 913 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1); 914 PetscValidHeaderSpecific(is, IS_CLASSID, 3); 915 PetscAssertPointer(newis, 4); 916 917 PetscCall(ISGetLocalSize(is, &n)); 918 PetscCall(ISGetIndices(is, &idxin)); 919 if (type == IS_GTOLM_MASK) { 920 PetscCall(PetscMalloc1(n, &idxout)); 921 } else { 922 PetscCall(ISGlobalToLocalMappingApply(mapping, type, n, idxin, &nout, NULL)); 923 PetscCall(PetscMalloc1(nout, &idxout)); 924 } 925 PetscCall(ISGlobalToLocalMappingApply(mapping, type, n, idxin, &nout, idxout)); 926 PetscCall(ISRestoreIndices(is, &idxin)); 927 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nout, idxout, PETSC_OWN_POINTER, newis)); 928 PetscFunctionReturn(PETSC_SUCCESS); 929 } 930 931 /*@ 932 ISGlobalToLocalMappingApplyBlock - Provides the local block numbering for a list of integers 933 specified with a block global numbering. 934 935 Not Collective 936 937 Input Parameters: 938 + mapping - mapping between local and global numbering 939 . type - `IS_GTOLM_MASK` - maps global indices with no local value to -1 in the output list (i.e., mask them) 940 `IS_GTOLM_DROP` - drops the indices with no local value from the output list 941 . n - number of global indices to map 942 - idx - global indices to map 943 944 Output Parameters: 945 + nout - number of indices in output array (if type == `IS_GTOLM_MASK` then nout = n) 946 - idxout - local index of each global index, one must pass in an array long enough 947 to hold all the indices. You can call `ISGlobalToLocalMappingApplyBlock()` with 948 idxout == NULL to determine the required length (returned in nout) 949 and then allocate the required space and call `ISGlobalToLocalMappingApplyBlock()` 950 a second time to set the values. 951 952 Level: advanced 953 954 Notes: 955 Either `nout` or `idxout` may be `NULL`. `idx` and `idxout` may be identical. 956 957 For "small" problems when using `ISGlobalToLocalMappingApply()` and `ISGlobalToLocalMappingApplyBlock()`, the `ISLocalToGlobalMappingType` of 958 `ISLOCALTOGLOBALMAPPINGBASIC` will be used; 959 this uses more memory but is faster; this approach is not scalable for extremely large mappings. For large problems `ISLOCALTOGLOBALMAPPINGHASH` is used, this is scalable. 960 Use `ISLocalToGlobalMappingSetType()` or call `ISLocalToGlobalMappingSetFromOptions()` with the option -islocaltoglobalmapping_type <basic,hash> to control which is used. 961 962 Developer Notes: 963 The manual page states that `idx` and `idxout` may be identical but the calling 964 sequence declares `idx` as const so it cannot be the same as `idxout`. 965 966 .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingApply()`, `ISGlobalToLocalMappingApply()`, `ISLocalToGlobalMappingCreate()`, 967 `ISLocalToGlobalMappingDestroy()` 968 @*/ 969 PetscErrorCode ISGlobalToLocalMappingApplyBlock(ISLocalToGlobalMapping mapping, ISGlobalToLocalMappingMode type, PetscInt n, const PetscInt idx[], PetscInt *nout, PetscInt idxout[]) 970 { 971 PetscFunctionBegin; 972 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1); 973 if (!mapping->data) PetscCall(ISGlobalToLocalMappingSetUp(mapping)); 974 PetscUseTypeMethod(mapping, globaltolocalmappingapplyblock, type, n, idx, nout, idxout); 975 PetscFunctionReturn(PETSC_SUCCESS); 976 } 977 978 /*@C 979 ISLocalToGlobalMappingGetBlockInfo - Gets the neighbor information 980 981 Collective the first time it is called 982 983 Input Parameter: 984 . mapping - the mapping from local to global indexing 985 986 Output Parameters: 987 + nproc - number of processes that are connected to the calling process 988 . procs - neighboring processes 989 . numprocs - number of block indices for each process 990 - indices - block indices (in local numbering) shared with neighbors (sorted by global numbering) 991 992 Level: advanced 993 994 .seealso: [](sec_scatter), `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`, 995 `ISLocalToGlobalMappingRestoreBlockInfo()` 996 @*/ 997 PetscErrorCode ISLocalToGlobalMappingGetBlockInfo(ISLocalToGlobalMapping mapping, PetscInt *nproc, PetscInt *procs[], PetscInt *numprocs[], PetscInt **indices[]) 998 { 999 PetscFunctionBegin; 1000 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1); 1001 PetscCall(ISLocalToGlobalMappingSetUpBlockInfo_Private(mapping)); 1002 if (nproc) *nproc = mapping->info_nproc; 1003 if (procs) *procs = mapping->info_procs; 1004 if (numprocs) *numprocs = mapping->info_numprocs; 1005 if (indices) *indices = mapping->info_indices; 1006 PetscFunctionReturn(PETSC_SUCCESS); 1007 } 1008 1009 /*@C 1010 ISLocalToGlobalMappingGetBlockNodeInfo - Gets the neighbor information for each local block index 1011 1012 Collective the first time it is called 1013 1014 Input Parameter: 1015 . mapping - the mapping from local to global indexing 1016 1017 Output Parameter: 1018 + n - number of local block nodes 1019 . n_procs - an array storing the number of processes for each local block node (including self) 1020 - procs - the processes' rank for each local block node (sorted, self is first) 1021 1022 Level: advanced 1023 1024 Notes: 1025 The user needs to call `ISLocalToGlobalMappingRestoreBlockNodeInfo()` when the data is no longer needed. 1026 The information returned by this function complements that of `ISLocalToGlobalMappingGetBlockInfo()`. 1027 The latter only provides local information, and the neighboring information 1028 cannot be inferred in the general case, unless the mapping is locally one-to-one on each process. 1029 1030 .seealso: `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`, 1031 `ISLocalToGlobalMappingGetBlockInfo()`, `ISLocalToGlobalMappingRestoreBlockNodeInfo()`, `ISLocalToGlobalMappingGetNodeInfo()` 1032 @*/ 1033 PetscErrorCode ISLocalToGlobalMappingGetBlockNodeInfo(ISLocalToGlobalMapping mapping, PetscInt *n, PetscInt *n_procs[], PetscInt **procs[]) 1034 { 1035 PetscFunctionBegin; 1036 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1); 1037 PetscCall(ISLocalToGlobalMappingSetUpBlockInfo_Private(mapping)); 1038 if (n) *n = mapping->n; 1039 if (n_procs) *n_procs = mapping->info_nodec; 1040 if (procs) *procs = mapping->info_nodei; 1041 PetscFunctionReturn(PETSC_SUCCESS); 1042 } 1043 1044 /*@C 1045 ISLocalToGlobalMappingRestoreBlockNodeInfo - Frees the memory allocated by `ISLocalToGlobalMappingGetBlockNodeInfo()` 1046 1047 Not Collective 1048 1049 Input Parameters: 1050 + mapping - the mapping from local to global indexing 1051 . n - number of local block nodes 1052 . n_procs - an array storing the number of processes for each local block nodes (including self) 1053 - procs - the processes' rank for each local block node (sorted, self is first) 1054 1055 Level: advanced 1056 1057 .seealso: `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`, 1058 `ISLocalToGlobalMappingGetBlockNodeInfo()` 1059 @*/ 1060 PetscErrorCode ISLocalToGlobalMappingRestoreBlockNodeInfo(ISLocalToGlobalMapping mapping, PetscInt *n, PetscInt *n_procs[], PetscInt **procs[]) 1061 { 1062 PetscFunctionBegin; 1063 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1); 1064 if (n) *n = 0; 1065 if (n_procs) *n_procs = NULL; 1066 if (procs) *procs = NULL; 1067 PetscFunctionReturn(PETSC_SUCCESS); 1068 } 1069 1070 static PetscErrorCode ISLocalToGlobalMappingSetUpBlockInfo_Private(ISLocalToGlobalMapping mapping) 1071 { 1072 PetscSF sf; 1073 MPI_Comm comm; 1074 const PetscSFNode *sfnode; 1075 PetscSFNode *newsfnode; 1076 PetscLayout layout; 1077 PetscHMapI neighs; 1078 PetscHashIter iter; 1079 PetscBool missing; 1080 const PetscInt *gidxs, *rootdegree; 1081 PetscInt *mask, *mrootdata, *leafdata, *newleafdata, *leafrd, *tmpg; 1082 PetscInt nroots, nleaves, newnleaves, bs, i, j, m, mnroots, p; 1083 PetscMPIInt rank, size; 1084 1085 PetscFunctionBegin; 1086 if (mapping->info_numprocs) PetscFunctionReturn(PETSC_SUCCESS); 1087 PetscCall(PetscObjectGetComm((PetscObject)mapping, &comm)); 1088 PetscCallMPI(MPI_Comm_size(comm, &size)); 1089 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1090 1091 /* Get mapping indices */ 1092 PetscCall(ISLocalToGlobalMappingGetBlockSize(mapping, &bs)); 1093 PetscCall(ISLocalToGlobalMappingGetBlockIndices(mapping, &gidxs)); 1094 PetscCall(ISLocalToGlobalMappingGetSize(mapping, &nleaves)); 1095 nleaves /= bs; 1096 1097 /* Create layout for global indices */ 1098 for (i = 0, m = 0; i < nleaves; i++) m = PetscMax(m, gidxs[i]); 1099 PetscCall(MPIU_Allreduce(MPI_IN_PLACE, &m, 1, MPIU_INT, MPI_MAX, comm)); 1100 PetscCall(PetscLayoutCreate(comm, &layout)); 1101 PetscCall(PetscLayoutSetSize(layout, m + 1)); 1102 PetscCall(PetscLayoutSetUp(layout)); 1103 1104 /* Create SF to share global indices */ 1105 PetscCall(PetscSFCreate(comm, &sf)); 1106 PetscCall(PetscSFSetGraphLayout(sf, layout, nleaves, NULL, PETSC_OWN_POINTER, gidxs)); 1107 PetscCall(PetscSFSetUp(sf)); 1108 PetscCall(PetscLayoutDestroy(&layout)); 1109 1110 /* communicate root degree to leaves */ 1111 PetscCall(PetscSFGetGraph(sf, &nroots, NULL, NULL, &sfnode)); 1112 PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree)); 1113 PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree)); 1114 for (i = 0, mnroots = 0; i < nroots; i++) mnroots += rootdegree[i]; 1115 PetscCall(PetscMalloc3(2 * PetscMax(mnroots, nroots), &mrootdata, 2 * nleaves, &leafdata, nleaves, &leafrd)); 1116 for (i = 0, m = 0; i < nroots; i++) { 1117 mrootdata[2 * i + 0] = rootdegree[i]; 1118 mrootdata[2 * i + 1] = m; 1119 m += rootdegree[i]; 1120 } 1121 PetscCall(PetscSFBcastBegin(sf, MPIU_2INT, mrootdata, leafdata, MPI_REPLACE)); 1122 PetscCall(PetscSFBcastEnd(sf, MPIU_2INT, mrootdata, leafdata, MPI_REPLACE)); 1123 1124 /* allocate enough space to store ranks */ 1125 for (i = 0, newnleaves = 0; i < nleaves; i++) { 1126 newnleaves += leafdata[2 * i]; 1127 leafrd[i] = leafdata[2 * i]; 1128 } 1129 1130 /* create new SF nodes to collect multi-root data at leaves */ 1131 PetscCall(PetscMalloc1(newnleaves, &newsfnode)); 1132 for (i = 0, m = 0; i < nleaves; i++) { 1133 for (j = 0; j < leafrd[i]; j++) { 1134 newsfnode[m].rank = sfnode[i].rank; 1135 newsfnode[m].index = leafdata[2 * i + 1] + j; 1136 m++; 1137 } 1138 } 1139 1140 /* gather ranks at multi roots */ 1141 for (i = 0; i < mnroots; i++) mrootdata[i] = -1; 1142 for (i = 0; i < nleaves; i++) leafdata[i] = (PetscInt)rank; 1143 1144 PetscCall(PetscSFGatherBegin(sf, MPIU_INT, leafdata, mrootdata)); 1145 PetscCall(PetscSFGatherEnd(sf, MPIU_INT, leafdata, mrootdata)); 1146 1147 /* set new multi-leaves graph into the SF */ 1148 PetscCall(PetscSFSetGraph(sf, mnroots, newnleaves, NULL, PETSC_OWN_POINTER, newsfnode, PETSC_OWN_POINTER)); 1149 PetscCall(PetscSFSetUp(sf)); 1150 1151 /* broadcast multi-root data to multi-leaves */ 1152 PetscCall(PetscMalloc1(newnleaves, &newleafdata)); 1153 PetscCall(PetscSFBcastBegin(sf, MPIU_INT, mrootdata, newleafdata, MPI_REPLACE)); 1154 PetscCall(PetscSFBcastEnd(sf, MPIU_INT, mrootdata, newleafdata, MPI_REPLACE)); 1155 1156 /* sort sharing ranks */ 1157 for (i = 0, m = 0; i < nleaves; i++) { 1158 PetscCall(PetscSortInt(leafrd[i], newleafdata + m)); 1159 m += leafrd[i]; 1160 } 1161 1162 /* Number of neighbors and their ranks */ 1163 PetscCall(PetscHMapICreate(&neighs)); 1164 for (i = 0; i < newnleaves; i++) PetscCall(PetscHMapIPut(neighs, newleafdata[i], &iter, &missing)); 1165 PetscCall(PetscHMapIGetSize(neighs, &mapping->info_nproc)); 1166 PetscCall(PetscMalloc1(mapping->info_nproc + 1, &mapping->info_procs)); 1167 PetscCall(PetscHMapIGetKeys(neighs, (i = 0, &i), mapping->info_procs)); 1168 for (i = 0; i < mapping->info_nproc; i++) { /* put info for self first */ 1169 if (mapping->info_procs[i] == rank) { 1170 PetscInt newr = mapping->info_procs[0]; 1171 1172 mapping->info_procs[0] = rank; 1173 mapping->info_procs[i] = newr; 1174 break; 1175 } 1176 } 1177 if (mapping->info_nproc) PetscCall(PetscSortInt(mapping->info_nproc - 1, mapping->info_procs + 1)); 1178 PetscCall(PetscHMapIDestroy(&neighs)); 1179 1180 /* collect info data */ 1181 PetscCall(PetscMalloc1(mapping->info_nproc + 1, &mapping->info_numprocs)); 1182 PetscCall(PetscMalloc1(mapping->info_nproc + 1, &mapping->info_indices)); 1183 for (i = 0; i < mapping->info_nproc + 1; i++) mapping->info_indices[i] = NULL; 1184 1185 PetscCall(PetscMalloc1(nleaves, &mask)); 1186 PetscCall(PetscMalloc1(nleaves, &tmpg)); 1187 for (p = 0; p < mapping->info_nproc; p++) { 1188 PetscInt *tmp, trank = mapping->info_procs[p]; 1189 1190 PetscCall(PetscMemzero(mask, nleaves * sizeof(*mask))); 1191 for (i = 0, m = 0; i < nleaves; i++) { 1192 for (j = 0; j < leafrd[i]; j++) { 1193 if (newleafdata[m] == trank) mask[i]++; 1194 if (!p && newleafdata[m] != rank) mask[i]++; 1195 m++; 1196 } 1197 } 1198 for (i = 0, m = 0; i < nleaves; i++) 1199 if (mask[i] > (!p ? 1 : 0)) m++; 1200 1201 PetscCall(PetscMalloc1(m, &tmp)); 1202 for (i = 0, m = 0; i < nleaves; i++) 1203 if (mask[i] > (!p ? 1 : 0)) { 1204 tmp[m] = i; 1205 tmpg[m] = gidxs[i]; 1206 m++; 1207 } 1208 PetscCall(PetscSortIntWithArray(m, tmpg, tmp)); 1209 mapping->info_indices[p] = tmp; 1210 mapping->info_numprocs[p] = m; 1211 } 1212 1213 /* Node info */ 1214 PetscCall(PetscMalloc2(nleaves, &mapping->info_nodec, nleaves + 1, &mapping->info_nodei)); 1215 PetscCall(PetscArraycpy(mapping->info_nodec, leafrd, nleaves)); 1216 PetscCall(PetscMalloc1(newnleaves, &mapping->info_nodei[0])); 1217 for (i = 0; i < nleaves - 1; i++) mapping->info_nodei[i + 1] = mapping->info_nodei[i] + mapping->info_nodec[i]; 1218 PetscCall(PetscArraycpy(mapping->info_nodei[0], newleafdata, newnleaves)); 1219 1220 PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(mapping, &gidxs)); 1221 PetscCall(PetscFree(tmpg)); 1222 PetscCall(PetscFree(mask)); 1223 PetscCall(PetscSFDestroy(&sf)); 1224 PetscCall(PetscFree3(mrootdata, leafdata, leafrd)); 1225 PetscCall(PetscFree(newleafdata)); 1226 PetscFunctionReturn(PETSC_SUCCESS); 1227 } 1228 1229 /*@C 1230 ISLocalToGlobalMappingRestoreBlockInfo - Frees the memory allocated by `ISLocalToGlobalMappingGetBlockInfo()` 1231 1232 Not Collective 1233 1234 Input Parameters: 1235 + mapping - the mapping from local to global indexing 1236 . nproc - number of processes that are connected to the calling process 1237 . procs - neighboring processes 1238 . numprocs - number of block indices for each process 1239 - indices - block indices (in local numbering) shared with neighbors (sorted by global numbering) 1240 1241 Level: advanced 1242 1243 .seealso: [](sec_scatter), `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`, 1244 `ISLocalToGlobalMappingGetInfo()` 1245 @*/ 1246 PetscErrorCode ISLocalToGlobalMappingRestoreBlockInfo(ISLocalToGlobalMapping mapping, PetscInt *nproc, PetscInt *procs[], PetscInt *numprocs[], PetscInt **indices[]) 1247 { 1248 PetscFunctionBegin; 1249 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1); 1250 if (nproc) *nproc = 0; 1251 if (procs) *procs = NULL; 1252 if (numprocs) *numprocs = NULL; 1253 if (indices) *indices = NULL; 1254 PetscFunctionReturn(PETSC_SUCCESS); 1255 } 1256 1257 /*@C 1258 ISLocalToGlobalMappingGetInfo - Gets the neighbor information for each process 1259 1260 Collective the first time it is called 1261 1262 Input Parameter: 1263 . mapping - the mapping from local to global indexing 1264 1265 Output Parameters: 1266 + nproc - number of processes that are connected to the calling process 1267 . procs - neighboring processes 1268 . numprocs - number of indices for each process 1269 - indices - indices (in local numbering) shared with neighbors (sorted by global numbering) 1270 1271 Level: advanced 1272 1273 Note: 1274 The user needs to call `ISLocalToGlobalMappingRestoreInfo()` when the data is no longer needed. 1275 1276 Fortran Notes: 1277 There is no `ISLocalToGlobalMappingRestoreInfo()` in Fortran. You must make sure that 1278 `procs`[], `numprocs`[] and `indices`[][] are large enough arrays, either by allocating them 1279 dynamically or defining static ones large enough. 1280 1281 .seealso: [](sec_scatter), `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`, 1282 `ISLocalToGlobalMappingRestoreInfo()`, `ISLocalToGlobalMappingGetNodeInfo()` 1283 @*/ 1284 PetscErrorCode ISLocalToGlobalMappingGetInfo(ISLocalToGlobalMapping mapping, PetscInt *nproc, PetscInt *procs[], PetscInt *numprocs[], PetscInt **indices[]) 1285 { 1286 PetscInt **bindices = NULL, *bnumprocs = NULL, bs, i, j, k, n, *bprocs; 1287 1288 PetscFunctionBegin; 1289 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1); 1290 bs = mapping->bs; 1291 PetscCall(ISLocalToGlobalMappingGetBlockInfo(mapping, &n, &bprocs, &bnumprocs, &bindices)); 1292 if (bs > 1) { /* we need to expand the cached info */ 1293 if (indices) PetscCall(PetscCalloc1(n, indices)); 1294 if (numprocs) PetscCall(PetscCalloc1(n, numprocs)); 1295 if (indices || numprocs) { 1296 for (i = 0; i < n; i++) { 1297 if (indices) { 1298 PetscCall(PetscMalloc1(bs * bnumprocs[i], &(*indices)[i])); 1299 for (j = 0; j < bnumprocs[i]; j++) { 1300 for (k = 0; k < bs; k++) (*indices)[i][j * bs + k] = bs * bindices[i][j] + k; 1301 } 1302 } 1303 if (numprocs) (*numprocs)[i] = bnumprocs[i] * bs; 1304 } 1305 } 1306 } else { 1307 if (numprocs) *numprocs = bnumprocs; 1308 if (indices) *indices = bindices; 1309 } 1310 if (nproc) *nproc = n; 1311 if (procs) *procs = bprocs; 1312 PetscFunctionReturn(PETSC_SUCCESS); 1313 } 1314 1315 /*@C 1316 ISLocalToGlobalMappingRestoreInfo - Frees the memory allocated by `ISLocalToGlobalMappingGetInfo()` 1317 1318 Not Collective 1319 1320 Input Parameters: 1321 + mapping - the mapping from local to global indexing 1322 . nproc - number of processes that are connected to the calling process 1323 . procs - neighboring processes 1324 . numprocs - number of indices for each process 1325 - indices - indices (in local numbering) shared with neighbors (sorted by global numbering) 1326 1327 Level: advanced 1328 1329 .seealso: [](sec_scatter), `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`, 1330 `ISLocalToGlobalMappingGetInfo()` 1331 @*/ 1332 PetscErrorCode ISLocalToGlobalMappingRestoreInfo(ISLocalToGlobalMapping mapping, PetscInt *nproc, PetscInt *procs[], PetscInt *numprocs[], PetscInt **indices[]) 1333 { 1334 PetscFunctionBegin; 1335 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1); 1336 if (mapping->bs > 1) { 1337 if (numprocs) PetscCall(PetscFree(*numprocs)); 1338 if (indices) { 1339 if (*indices) 1340 for (PetscInt i = 0; i < *nproc; i++) PetscCall(PetscFree((*indices)[i])); 1341 PetscCall(PetscFree(*indices)); 1342 } 1343 } 1344 PetscFunctionReturn(PETSC_SUCCESS); 1345 } 1346 1347 /*@C 1348 ISLocalToGlobalMappingGetNodeInfo - Gets the neighbor information of local nodes 1349 1350 Collective the first time it is called 1351 1352 Input Parameter: 1353 . mapping - the mapping from local to global indexing 1354 1355 Output Parameters: 1356 + n - number of local nodes 1357 . n_procs - an array storing the number of processes for each local node (including self) 1358 - procs - the processes' rank for each local node (sorted, self is first) 1359 1360 Level: advanced 1361 1362 Note: 1363 The user needs to call `ISLocalToGlobalMappingRestoreNodeInfo()` when the data is no longer needed. 1364 1365 .seealso: [](sec_scatter), `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`, 1366 `ISLocalToGlobalMappingGetInfo()`, `ISLocalToGlobalMappingRestoreNodeInfo()`, `ISLocalToGlobalMappingGetBlockNodeInfo()` 1367 @*/ 1368 PetscErrorCode ISLocalToGlobalMappingGetNodeInfo(ISLocalToGlobalMapping mapping, PetscInt *n, PetscInt *n_procs[], PetscInt **procs[]) 1369 { 1370 PetscInt **bprocs = NULL, *bn_procs = NULL, bs, i, j, k, bn; 1371 1372 PetscFunctionBegin; 1373 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1); 1374 bs = mapping->bs; 1375 PetscCall(ISLocalToGlobalMappingGetBlockNodeInfo(mapping, &bn, &bn_procs, &bprocs)); 1376 if (bs > 1) { /* we need to expand the cached info */ 1377 PetscInt *tn_procs; 1378 PetscInt c; 1379 1380 PetscCall(PetscMalloc1(bn * bs, &tn_procs)); 1381 for (i = 0, c = 0; i < bn; i++) { 1382 for (k = 0; k < bs; k++) tn_procs[i * bs + k] = bn_procs[i]; 1383 c += bs * bn_procs[i]; 1384 } 1385 if (n) *n = bn * bs; 1386 if (procs) { 1387 PetscInt **tprocs; 1388 PetscInt tn = bn * bs; 1389 1390 PetscCall(PetscMalloc1(tn, &tprocs)); 1391 if (tn) PetscCall(PetscMalloc1(c, &tprocs[0])); 1392 for (i = 0; i < tn - 1; i++) tprocs[i + 1] = tprocs[i] + tn_procs[i]; 1393 for (i = 0; i < bn; i++) { 1394 for (k = 0; k < bs; k++) { 1395 for (j = 0; j < bn_procs[i]; j++) tprocs[i * bs + k][j] = bprocs[i][j]; 1396 } 1397 } 1398 *procs = tprocs; 1399 } 1400 if (n_procs) *n_procs = tn_procs; 1401 else PetscCall(PetscFree(tn_procs)); 1402 } else { 1403 if (n) *n = bn; 1404 if (n_procs) *n_procs = bn_procs; 1405 if (procs) *procs = bprocs; 1406 } 1407 PetscFunctionReturn(PETSC_SUCCESS); 1408 } 1409 1410 /*@C 1411 ISLocalToGlobalMappingRestoreNodeInfo - Frees the memory allocated by `ISLocalToGlobalMappingGetNodeInfo()` 1412 1413 Not Collective 1414 1415 Input Parameters: 1416 + mapping - the mapping from local to global indexing 1417 . n - number of local nodes 1418 . n_procs - an array storing the number of processes for each local node (including self) 1419 - procs - the processes' rank for each local node (sorted, self is first) 1420 1421 Level: advanced 1422 1423 .seealso: [](sec_scatter), `ISLocalToGlobalMappingDestroy()`, `ISLocalToGlobalMappingCreateIS()`, `ISLocalToGlobalMappingCreate()`, 1424 `ISLocalToGlobalMappingGetInfo()` 1425 @*/ 1426 PetscErrorCode ISLocalToGlobalMappingRestoreNodeInfo(ISLocalToGlobalMapping mapping, PetscInt *n, PetscInt *n_procs[], PetscInt **procs[]) 1427 { 1428 PetscFunctionBegin; 1429 PetscValidHeaderSpecific(mapping, IS_LTOGM_CLASSID, 1); 1430 if (mapping->bs > 1) { 1431 if (n_procs) PetscCall(PetscFree(*n_procs)); 1432 if (procs) { 1433 if (*procs) PetscCall(PetscFree((*procs)[0])); 1434 PetscCall(PetscFree(*procs)); 1435 } 1436 } 1437 PetscCall(ISLocalToGlobalMappingRestoreBlockNodeInfo(mapping, n, n_procs, procs)); 1438 PetscFunctionReturn(PETSC_SUCCESS); 1439 } 1440 1441 /*MC 1442 ISLocalToGlobalMappingGetIndicesF90 - Get global indices for every local point that is mapped 1443 1444 Synopsis: 1445 ISLocalToGlobalMappingGetIndicesF90(ISLocalToGlobalMapping ltog, PetscInt, pointer :: array(:)}, integer ierr) 1446 1447 Not Collective 1448 1449 Input Parameter: 1450 . A - the matrix 1451 1452 Output Parameter: 1453 . array - array of indices, the length of this array may be obtained with `ISLocalToGlobalMappingGetSize()` 1454 1455 Level: advanced 1456 1457 Note: 1458 Use `ISLocalToGlobalMappingGetIndicesF90()` when you no longer need access to the data 1459 1460 .seealso: [](sec_fortranarrays), [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingGetIndices()`, `ISLocalToGlobalMappingRestoreIndices()`, 1461 `ISLocalToGlobalMappingRestoreIndicesF90()` 1462 M*/ 1463 1464 /*MC 1465 ISLocalToGlobalMappingRestoreIndicesF90 - restores the global indices for every local point that is mapped obtained with `ISLocalToGlobalMappingGetIndicesF90()` 1466 1467 Synopsis: 1468 ISLocalToGlobalMappingRestoreIndicesF90(ISLocalToGlobalMapping ltog, PetscInt, pointer :: array(:)}, integer ierr) 1469 1470 Not Collective 1471 1472 Input Parameters: 1473 + A - the matrix 1474 - array - array of indices, the length of this array may be obtained with `ISLocalToGlobalMappingGetSize()` 1475 1476 Level: advanced 1477 1478 .seealso: [](sec_fortranarrays), [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingGetIndices()`, `ISLocalToGlobalMappingRestoreIndices()`, 1479 `ISLocalToGlobalMappingGetIndicesF90()` 1480 M*/ 1481 1482 /*@C 1483 ISLocalToGlobalMappingGetIndices - Get global indices for every local point that is mapped 1484 1485 Not Collective 1486 1487 Input Parameter: 1488 . ltog - local to global mapping 1489 1490 Output Parameter: 1491 . array - array of indices, the length of this array may be obtained with `ISLocalToGlobalMappingGetSize()` 1492 1493 Level: advanced 1494 1495 Note: 1496 `ISLocalToGlobalMappingGetSize()` returns the length the this array 1497 1498 .seealso: [](sec_scatter), `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingApply()`, `ISLocalToGlobalMappingRestoreIndices()`, 1499 `ISLocalToGlobalMappingGetBlockIndices()`, `ISLocalToGlobalMappingRestoreBlockIndices()` 1500 @*/ 1501 PetscErrorCode ISLocalToGlobalMappingGetIndices(ISLocalToGlobalMapping ltog, const PetscInt **array) 1502 { 1503 PetscFunctionBegin; 1504 PetscValidHeaderSpecific(ltog, IS_LTOGM_CLASSID, 1); 1505 PetscAssertPointer(array, 2); 1506 if (ltog->bs == 1) { 1507 *array = ltog->indices; 1508 } else { 1509 PetscInt *jj, k, i, j, n = ltog->n, bs = ltog->bs; 1510 const PetscInt *ii; 1511 1512 PetscCall(PetscMalloc1(bs * n, &jj)); 1513 *array = jj; 1514 k = 0; 1515 ii = ltog->indices; 1516 for (i = 0; i < n; i++) 1517 for (j = 0; j < bs; j++) jj[k++] = bs * ii[i] + j; 1518 } 1519 PetscFunctionReturn(PETSC_SUCCESS); 1520 } 1521 1522 /*@C 1523 ISLocalToGlobalMappingRestoreIndices - Restore indices obtained with `ISLocalToGlobalMappingGetIndices()` 1524 1525 Not Collective 1526 1527 Input Parameters: 1528 + ltog - local to global mapping 1529 - array - array of indices 1530 1531 Level: advanced 1532 1533 .seealso: [](sec_scatter), `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingApply()`, `ISLocalToGlobalMappingGetIndices()` 1534 @*/ 1535 PetscErrorCode ISLocalToGlobalMappingRestoreIndices(ISLocalToGlobalMapping ltog, const PetscInt **array) 1536 { 1537 PetscFunctionBegin; 1538 PetscValidHeaderSpecific(ltog, IS_LTOGM_CLASSID, 1); 1539 PetscAssertPointer(array, 2); 1540 PetscCheck(ltog->bs != 1 || *array == ltog->indices, PETSC_COMM_SELF, PETSC_ERR_ARG_BADPTR, "Trying to return mismatched pointer"); 1541 if (ltog->bs > 1) PetscCall(PetscFree(*(void **)array)); 1542 PetscFunctionReturn(PETSC_SUCCESS); 1543 } 1544 1545 /*@C 1546 ISLocalToGlobalMappingGetBlockIndices - Get global indices for every local block 1547 1548 Not Collective 1549 1550 Input Parameter: 1551 . ltog - local to global mapping 1552 1553 Output Parameter: 1554 . array - array of indices 1555 1556 Level: advanced 1557 1558 .seealso: [](sec_scatter), `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingApply()`, `ISLocalToGlobalMappingRestoreBlockIndices()` 1559 @*/ 1560 PetscErrorCode ISLocalToGlobalMappingGetBlockIndices(ISLocalToGlobalMapping ltog, const PetscInt **array) 1561 { 1562 PetscFunctionBegin; 1563 PetscValidHeaderSpecific(ltog, IS_LTOGM_CLASSID, 1); 1564 PetscAssertPointer(array, 2); 1565 *array = ltog->indices; 1566 PetscFunctionReturn(PETSC_SUCCESS); 1567 } 1568 1569 /*@C 1570 ISLocalToGlobalMappingRestoreBlockIndices - Restore indices obtained with `ISLocalToGlobalMappingGetBlockIndices()` 1571 1572 Not Collective 1573 1574 Input Parameters: 1575 + ltog - local to global mapping 1576 - array - array of indices 1577 1578 Level: advanced 1579 1580 .seealso: [](sec_scatter), `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingApply()`, `ISLocalToGlobalMappingGetIndices()` 1581 @*/ 1582 PetscErrorCode ISLocalToGlobalMappingRestoreBlockIndices(ISLocalToGlobalMapping ltog, const PetscInt **array) 1583 { 1584 PetscFunctionBegin; 1585 PetscValidHeaderSpecific(ltog, IS_LTOGM_CLASSID, 1); 1586 PetscAssertPointer(array, 2); 1587 PetscCheck(*array == ltog->indices, PETSC_COMM_SELF, PETSC_ERR_ARG_BADPTR, "Trying to return mismatched pointer"); 1588 *array = NULL; 1589 PetscFunctionReturn(PETSC_SUCCESS); 1590 } 1591 1592 /*@C 1593 ISLocalToGlobalMappingConcatenate - Create a new mapping that concatenates a list of mappings 1594 1595 Not Collective 1596 1597 Input Parameters: 1598 + comm - communicator for the new mapping, must contain the communicator of every mapping to concatenate 1599 . n - number of mappings to concatenate 1600 - ltogs - local to global mappings 1601 1602 Output Parameter: 1603 . ltogcat - new mapping 1604 1605 Level: advanced 1606 1607 Note: 1608 This currently always returns a mapping with block size of 1 1609 1610 Developer Notes: 1611 If all the input mapping have the same block size we could easily handle that as a special case 1612 1613 .seealso: [](sec_scatter), `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingCreate()` 1614 @*/ 1615 PetscErrorCode ISLocalToGlobalMappingConcatenate(MPI_Comm comm, PetscInt n, const ISLocalToGlobalMapping ltogs[], ISLocalToGlobalMapping *ltogcat) 1616 { 1617 PetscInt i, cnt, m, *idx; 1618 1619 PetscFunctionBegin; 1620 PetscCheck(n >= 0, comm, PETSC_ERR_ARG_OUTOFRANGE, "Must have a non-negative number of mappings, given %" PetscInt_FMT, n); 1621 if (n > 0) PetscAssertPointer(ltogs, 3); 1622 for (i = 0; i < n; i++) PetscValidHeaderSpecific(ltogs[i], IS_LTOGM_CLASSID, 3); 1623 PetscAssertPointer(ltogcat, 4); 1624 for (cnt = 0, i = 0; i < n; i++) { 1625 PetscCall(ISLocalToGlobalMappingGetSize(ltogs[i], &m)); 1626 cnt += m; 1627 } 1628 PetscCall(PetscMalloc1(cnt, &idx)); 1629 for (cnt = 0, i = 0; i < n; i++) { 1630 const PetscInt *subidx; 1631 PetscCall(ISLocalToGlobalMappingGetSize(ltogs[i], &m)); 1632 PetscCall(ISLocalToGlobalMappingGetIndices(ltogs[i], &subidx)); 1633 PetscCall(PetscArraycpy(&idx[cnt], subidx, m)); 1634 PetscCall(ISLocalToGlobalMappingRestoreIndices(ltogs[i], &subidx)); 1635 cnt += m; 1636 } 1637 PetscCall(ISLocalToGlobalMappingCreate(comm, 1, cnt, idx, PETSC_OWN_POINTER, ltogcat)); 1638 PetscFunctionReturn(PETSC_SUCCESS); 1639 } 1640 1641 /*MC 1642 ISLOCALTOGLOBALMAPPINGBASIC - basic implementation of the `ISLocalToGlobalMapping` object. When `ISGlobalToLocalMappingApply()` is 1643 used this is good for only small and moderate size problems. 1644 1645 Options Database Key: 1646 . -islocaltoglobalmapping_type basic - select this method 1647 1648 Level: beginner 1649 1650 Developer Note: 1651 This stores all the mapping information on each MPI rank. 1652 1653 .seealso: [](sec_scatter), `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingSetType()`, `ISLOCALTOGLOBALMAPPINGHASH` 1654 M*/ 1655 PETSC_EXTERN PetscErrorCode ISLocalToGlobalMappingCreate_Basic(ISLocalToGlobalMapping ltog) 1656 { 1657 PetscFunctionBegin; 1658 ltog->ops->globaltolocalmappingapply = ISGlobalToLocalMappingApply_Basic; 1659 ltog->ops->globaltolocalmappingsetup = ISGlobalToLocalMappingSetUp_Basic; 1660 ltog->ops->globaltolocalmappingapplyblock = ISGlobalToLocalMappingApplyBlock_Basic; 1661 ltog->ops->destroy = ISLocalToGlobalMappingDestroy_Basic; 1662 PetscFunctionReturn(PETSC_SUCCESS); 1663 } 1664 1665 /*MC 1666 ISLOCALTOGLOBALMAPPINGHASH - hash implementation of the `ISLocalToGlobalMapping` object. When `ISGlobalToLocalMappingApply()` is 1667 used this is good for large memory problems. 1668 1669 Options Database Key: 1670 . -islocaltoglobalmapping_type hash - select this method 1671 1672 Level: beginner 1673 1674 Note: 1675 This is selected automatically for large problems if the user does not set the type. 1676 1677 .seealso: [](sec_scatter), `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingSetType()`, `ISLOCALTOGLOBALMAPPINGBASIC` 1678 M*/ 1679 PETSC_EXTERN PetscErrorCode ISLocalToGlobalMappingCreate_Hash(ISLocalToGlobalMapping ltog) 1680 { 1681 PetscFunctionBegin; 1682 ltog->ops->globaltolocalmappingapply = ISGlobalToLocalMappingApply_Hash; 1683 ltog->ops->globaltolocalmappingsetup = ISGlobalToLocalMappingSetUp_Hash; 1684 ltog->ops->globaltolocalmappingapplyblock = ISGlobalToLocalMappingApplyBlock_Hash; 1685 ltog->ops->destroy = ISLocalToGlobalMappingDestroy_Hash; 1686 PetscFunctionReturn(PETSC_SUCCESS); 1687 } 1688 1689 /*@C 1690 ISLocalToGlobalMappingRegister - Registers a method for applying a global to local mapping with an `ISLocalToGlobalMapping` 1691 1692 Not Collective 1693 1694 Input Parameters: 1695 + sname - name of a new method 1696 - function - routine to create method context 1697 1698 Example Usage: 1699 .vb 1700 ISLocalToGlobalMappingRegister("my_mapper", MyCreate); 1701 .ve 1702 1703 Then, your mapping can be chosen with the procedural interface via 1704 $ ISLocalToGlobalMappingSetType(ltog, "my_mapper") 1705 or at runtime via the option 1706 $ -islocaltoglobalmapping_type my_mapper 1707 1708 Level: advanced 1709 1710 Note: 1711 `ISLocalToGlobalMappingRegister()` may be called multiple times to add several user-defined mappings. 1712 1713 .seealso: [](sec_scatter), `ISLocalToGlobalMappingRegisterAll()`, `ISLocalToGlobalMappingRegisterDestroy()`, `ISLOCALTOGLOBALMAPPINGBASIC`, 1714 `ISLOCALTOGLOBALMAPPINGHASH`, `ISLocalToGlobalMapping`, `ISLocalToGlobalMappingApply()` 1715 @*/ 1716 PetscErrorCode ISLocalToGlobalMappingRegister(const char sname[], PetscErrorCode (*function)(ISLocalToGlobalMapping)) 1717 { 1718 PetscFunctionBegin; 1719 PetscCall(ISInitializePackage()); 1720 PetscCall(PetscFunctionListAdd(&ISLocalToGlobalMappingList, sname, function)); 1721 PetscFunctionReturn(PETSC_SUCCESS); 1722 } 1723 1724 /*@C 1725 ISLocalToGlobalMappingSetType - Sets the implementation type `ISLocalToGlobalMapping` will use 1726 1727 Logically Collective 1728 1729 Input Parameters: 1730 + ltog - the `ISLocalToGlobalMapping` object 1731 - type - a known method 1732 1733 Options Database Key: 1734 . -islocaltoglobalmapping_type <method> - Sets the method; use -help for a list of available methods (for instance, basic or hash) 1735 1736 Level: intermediate 1737 1738 Notes: 1739 See `ISLocalToGlobalMappingType` for available methods 1740 1741 Normally, it is best to use the `ISLocalToGlobalMappingSetFromOptions()` command and 1742 then set the `ISLocalToGlobalMappingType` from the options database rather than by using 1743 this routine. 1744 1745 Developer Notes: 1746 `ISLocalToGlobalMappingRegister()` is used to add new types to `ISLocalToGlobalMappingList` from which they 1747 are accessed by `ISLocalToGlobalMappingSetType()`. 1748 1749 .seealso: [](sec_scatter), `ISLocalToGlobalMappingType`, `ISLocalToGlobalMappingRegister()`, `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingGetType()` 1750 @*/ 1751 PetscErrorCode ISLocalToGlobalMappingSetType(ISLocalToGlobalMapping ltog, ISLocalToGlobalMappingType type) 1752 { 1753 PetscBool match; 1754 PetscErrorCode (*r)(ISLocalToGlobalMapping) = NULL; 1755 1756 PetscFunctionBegin; 1757 PetscValidHeaderSpecific(ltog, IS_LTOGM_CLASSID, 1); 1758 if (type) PetscAssertPointer(type, 2); 1759 1760 PetscCall(PetscObjectTypeCompare((PetscObject)ltog, type, &match)); 1761 if (match) PetscFunctionReturn(PETSC_SUCCESS); 1762 1763 /* L2G maps defer type setup at globaltolocal calls, allow passing NULL here */ 1764 if (type) { 1765 PetscCall(PetscFunctionListFind(ISLocalToGlobalMappingList, type, &r)); 1766 PetscCheck(r, PetscObjectComm((PetscObject)ltog), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested ISLocalToGlobalMapping type %s", type); 1767 } 1768 /* Destroy the previous private LTOG context */ 1769 PetscTryTypeMethod(ltog, destroy); 1770 ltog->ops->destroy = NULL; 1771 1772 PetscCall(PetscObjectChangeTypeName((PetscObject)ltog, type)); 1773 if (r) PetscCall((*r)(ltog)); 1774 PetscFunctionReturn(PETSC_SUCCESS); 1775 } 1776 1777 /*@C 1778 ISLocalToGlobalMappingGetType - Get the type of the `ISLocalToGlobalMapping` 1779 1780 Not Collective 1781 1782 Input Parameter: 1783 . ltog - the `ISLocalToGlobalMapping` object 1784 1785 Output Parameter: 1786 . type - the type 1787 1788 Level: intermediate 1789 1790 .seealso: [](sec_scatter), `ISLocalToGlobalMappingType`, `ISLocalToGlobalMappingRegister()`, `ISLocalToGlobalMappingCreate()`, `ISLocalToGlobalMappingSetType()` 1791 @*/ 1792 PetscErrorCode ISLocalToGlobalMappingGetType(ISLocalToGlobalMapping ltog, ISLocalToGlobalMappingType *type) 1793 { 1794 PetscFunctionBegin; 1795 PetscValidHeaderSpecific(ltog, IS_LTOGM_CLASSID, 1); 1796 PetscAssertPointer(type, 2); 1797 *type = ((PetscObject)ltog)->type_name; 1798 PetscFunctionReturn(PETSC_SUCCESS); 1799 } 1800 1801 PetscBool ISLocalToGlobalMappingRegisterAllCalled = PETSC_FALSE; 1802 1803 /*@C 1804 ISLocalToGlobalMappingRegisterAll - Registers all of the local to global mapping components in the `IS` package. 1805 1806 Not Collective 1807 1808 Level: advanced 1809 1810 .seealso: [](sec_scatter), `ISRegister()`, `ISLocalToGlobalRegister()` 1811 @*/ 1812 PetscErrorCode ISLocalToGlobalMappingRegisterAll(void) 1813 { 1814 PetscFunctionBegin; 1815 if (ISLocalToGlobalMappingRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS); 1816 ISLocalToGlobalMappingRegisterAllCalled = PETSC_TRUE; 1817 PetscCall(ISLocalToGlobalMappingRegister(ISLOCALTOGLOBALMAPPINGBASIC, ISLocalToGlobalMappingCreate_Basic)); 1818 PetscCall(ISLocalToGlobalMappingRegister(ISLOCALTOGLOBALMAPPINGHASH, ISLocalToGlobalMappingCreate_Hash)); 1819 PetscFunctionReturn(PETSC_SUCCESS); 1820 } 1821