1 #include <../src/dm/impls/composite/packimpl.h> /*I "petscdmcomposite.h" I*/ 2 #include <petsc/private/isimpl.h> 3 #include <petsc/private/glvisviewerimpl.h> 4 #include <petscds.h> 5 6 /*@C 7 DMCompositeSetCoupling - Sets user provided routines that compute the coupling between the 8 separate components `DM` in a `DMCOMPOSITE` to build the correct matrix nonzero structure. 9 10 Logically Collective; No Fortran Support 11 12 Input Parameters: 13 + dm - the composite object 14 - FormCoupleLocations - routine to set the nonzero locations in the matrix 15 16 Level: advanced 17 18 Note: 19 See `DMSetApplicationContext()` and `DMGetApplicationContext()` for how to get user information into 20 this routine 21 22 .seealso: `DMCOMPOSITE`, `DM` 23 @*/ 24 PetscErrorCode DMCompositeSetCoupling(DM dm, PetscErrorCode (*FormCoupleLocations)(DM, Mat, PetscInt *, PetscInt *, PetscInt, PetscInt, PetscInt, PetscInt)) 25 { 26 DM_Composite *com = (DM_Composite *)dm->data; 27 PetscBool flg; 28 29 PetscFunctionBegin; 30 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg)); 31 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name); 32 com->FormCoupleLocations = FormCoupleLocations; 33 PetscFunctionReturn(PETSC_SUCCESS); 34 } 35 36 static PetscErrorCode DMDestroy_Composite(DM dm) 37 { 38 struct DMCompositeLink *next, *prev; 39 DM_Composite *com = (DM_Composite *)dm->data; 40 41 PetscFunctionBegin; 42 next = com->next; 43 while (next) { 44 prev = next; 45 next = next->next; 46 PetscCall(DMDestroy(&prev->dm)); 47 PetscCall(PetscFree(prev->grstarts)); 48 PetscCall(PetscFree(prev)); 49 } 50 PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", NULL)); 51 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 52 PetscCall(PetscFree(com)); 53 PetscFunctionReturn(PETSC_SUCCESS); 54 } 55 56 static PetscErrorCode DMView_Composite(DM dm, PetscViewer v) 57 { 58 PetscBool iascii; 59 DM_Composite *com = (DM_Composite *)dm->data; 60 61 PetscFunctionBegin; 62 PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &iascii)); 63 if (iascii) { 64 struct DMCompositeLink *lnk = com->next; 65 PetscInt i; 66 67 PetscCall(PetscViewerASCIIPrintf(v, "DM (%s)\n", ((PetscObject)dm)->prefix ? ((PetscObject)dm)->prefix : "no prefix")); 68 PetscCall(PetscViewerASCIIPrintf(v, " contains %" PetscInt_FMT " DMs\n", com->nDM)); 69 PetscCall(PetscViewerASCIIPushTab(v)); 70 for (i = 0; lnk; lnk = lnk->next, i++) { 71 PetscCall(PetscViewerASCIIPrintf(v, "Link %" PetscInt_FMT ": DM of type %s\n", i, ((PetscObject)lnk->dm)->type_name)); 72 PetscCall(PetscViewerASCIIPushTab(v)); 73 PetscCall(DMView(lnk->dm, v)); 74 PetscCall(PetscViewerASCIIPopTab(v)); 75 } 76 PetscCall(PetscViewerASCIIPopTab(v)); 77 } 78 PetscFunctionReturn(PETSC_SUCCESS); 79 } 80 81 /* --------------------------------------------------------------------------------------*/ 82 static PetscErrorCode DMSetUp_Composite(DM dm) 83 { 84 PetscInt nprev = 0; 85 PetscMPIInt rank, size; 86 DM_Composite *com = (DM_Composite *)dm->data; 87 struct DMCompositeLink *next = com->next; 88 PetscLayout map; 89 90 PetscFunctionBegin; 91 PetscCheck(!com->setup, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Packer has already been setup"); 92 PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &map)); 93 PetscCall(PetscLayoutSetLocalSize(map, com->n)); 94 PetscCall(PetscLayoutSetSize(map, PETSC_DETERMINE)); 95 PetscCall(PetscLayoutSetBlockSize(map, 1)); 96 PetscCall(PetscLayoutSetUp(map)); 97 PetscCall(PetscLayoutGetSize(map, &com->N)); 98 PetscCall(PetscLayoutGetRange(map, &com->rstart, NULL)); 99 PetscCall(PetscLayoutDestroy(&map)); 100 101 /* now set the rstart for each linked vector */ 102 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 103 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 104 while (next) { 105 next->rstart = nprev; 106 nprev += next->n; 107 next->grstart = com->rstart + next->rstart; 108 PetscCall(PetscMalloc1(size, &next->grstarts)); 109 PetscCallMPI(MPI_Allgather(&next->grstart, 1, MPIU_INT, next->grstarts, 1, MPIU_INT, PetscObjectComm((PetscObject)dm))); 110 next = next->next; 111 } 112 com->setup = PETSC_TRUE; 113 PetscFunctionReturn(PETSC_SUCCESS); 114 } 115 116 /*@ 117 DMCompositeGetNumberDM - Gets the number of `DM` objects in the `DMCOMPOSITE` 118 representation. 119 120 Not Collective 121 122 Input Parameter: 123 . dm - the `DMCOMPOSITE` object 124 125 Output Parameter: 126 . nDM - the number of `DM` 127 128 Level: beginner 129 130 .seealso: `DMCOMPOSITE`, `DM` 131 @*/ 132 PetscErrorCode DMCompositeGetNumberDM(DM dm, PetscInt *nDM) 133 { 134 DM_Composite *com = (DM_Composite *)dm->data; 135 PetscBool flg; 136 137 PetscFunctionBegin; 138 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 139 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg)); 140 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name); 141 *nDM = com->nDM; 142 PetscFunctionReturn(PETSC_SUCCESS); 143 } 144 145 /*@C 146 DMCompositeGetAccess - Allows one to access the individual packed vectors in their global 147 representation. 148 149 Collective 150 151 Input Parameters: 152 + dm - the `DMCOMPOSITE` object 153 - gvec - the global vector 154 155 Output Parameter: 156 . ... - the packed parallel vectors, `NULL` for those that are not needed 157 158 Level: advanced 159 160 Note: 161 Use `DMCompositeRestoreAccess()` to return the vectors when you no longer need them 162 163 .seealso: `DMCOMPOSITE`, `DM`, `DMCompositeGetEntries()`, `DMCompositeScatter()` 164 @*/ 165 PetscErrorCode DMCompositeGetAccess(DM dm, Vec gvec, ...) 166 { 167 va_list Argp; 168 struct DMCompositeLink *next; 169 DM_Composite *com = (DM_Composite *)dm->data; 170 PetscInt readonly; 171 PetscBool flg; 172 173 PetscFunctionBegin; 174 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 175 PetscValidHeaderSpecific(gvec, VEC_CLASSID, 2); 176 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg)); 177 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name); 178 next = com->next; 179 if (!com->setup) PetscCall(DMSetUp(dm)); 180 181 PetscCall(VecLockGet(gvec, &readonly)); 182 /* loop over packed objects, handling one at a time */ 183 va_start(Argp, gvec); 184 while (next) { 185 Vec *vec; 186 vec = va_arg(Argp, Vec *); 187 if (vec) { 188 PetscCall(DMGetGlobalVector(next->dm, vec)); 189 if (readonly) { 190 const PetscScalar *array; 191 PetscCall(VecGetArrayRead(gvec, &array)); 192 PetscCall(VecPlaceArray(*vec, array + next->rstart)); 193 PetscCall(VecLockReadPush(*vec)); 194 PetscCall(VecRestoreArrayRead(gvec, &array)); 195 } else { 196 PetscScalar *array; 197 PetscCall(VecGetArray(gvec, &array)); 198 PetscCall(VecPlaceArray(*vec, array + next->rstart)); 199 PetscCall(VecRestoreArray(gvec, &array)); 200 } 201 } 202 next = next->next; 203 } 204 va_end(Argp); 205 PetscFunctionReturn(PETSC_SUCCESS); 206 } 207 208 /*@ 209 DMCompositeGetAccessArray - Allows one to access the individual packed vectors in their global 210 representation. 211 212 Collective 213 214 Input Parameters: 215 + dm - the `DMCOMPOSITE` 216 . pvec - packed vector 217 . nwanted - number of vectors wanted 218 - wanted - sorted array of integers indicating thde vectors wanted, or `NULL` to get all vectors, length `nwanted` 219 220 Output Parameter: 221 . vecs - array of requested global vectors (must be previously allocated and of length `nwanted`) 222 223 Level: advanced 224 225 Note: 226 Use `DMCompositeRestoreAccessArray()` to return the vectors when you no longer need them 227 228 .seealso: `DMCOMPOSITE`, `DM`, `DMCompositeGetAccess()`, `DMCompositeGetEntries()`, `DMCompositeScatter()`, `DMCompositeGather()` 229 @*/ 230 PetscErrorCode DMCompositeGetAccessArray(DM dm, Vec pvec, PetscInt nwanted, const PetscInt wanted[], Vec vecs[]) 231 { 232 struct DMCompositeLink *link; 233 PetscInt i, wnum; 234 DM_Composite *com = (DM_Composite *)dm->data; 235 PetscInt readonly; 236 PetscBool flg; 237 238 PetscFunctionBegin; 239 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 240 PetscValidHeaderSpecific(pvec, VEC_CLASSID, 2); 241 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg)); 242 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name); 243 if (!com->setup) PetscCall(DMSetUp(dm)); 244 245 PetscCall(VecLockGet(pvec, &readonly)); 246 for (i = 0, wnum = 0, link = com->next; link && wnum < nwanted; i++, link = link->next) { 247 if (!wanted || i == wanted[wnum]) { 248 Vec v; 249 PetscCall(DMGetGlobalVector(link->dm, &v)); 250 if (readonly) { 251 const PetscScalar *array; 252 PetscCall(VecGetArrayRead(pvec, &array)); 253 PetscCall(VecPlaceArray(v, array + link->rstart)); 254 PetscCall(VecLockReadPush(v)); 255 PetscCall(VecRestoreArrayRead(pvec, &array)); 256 } else { 257 PetscScalar *array; 258 PetscCall(VecGetArray(pvec, &array)); 259 PetscCall(VecPlaceArray(v, array + link->rstart)); 260 PetscCall(VecRestoreArray(pvec, &array)); 261 } 262 vecs[wnum++] = v; 263 } 264 } 265 PetscFunctionReturn(PETSC_SUCCESS); 266 } 267 268 /*@ 269 DMCompositeGetLocalAccessArray - Allows one to access the individual 270 packed vectors in their local representation. 271 272 Collective 273 274 Input Parameters: 275 + dm - the `DMCOMPOSITE` 276 . pvec - packed vector 277 . nwanted - number of vectors wanted 278 - wanted - sorted array of vectors wanted, or `NULL` to get all vectors, length `nwanted` 279 280 Output Parameter: 281 . vecs - array of requested local vectors (must be allocated and of length `nwanted`) 282 283 Level: advanced 284 285 Note: 286 Use `DMCompositeRestoreLocalAccessArray()` to return the vectors 287 when you no longer need them. 288 289 .seealso: `DMCOMPOSITE`, `DM`, `DMCompositeRestoreLocalAccessArray()`, `DMCompositeGetAccess()`, 290 `DMCompositeGetEntries()`, `DMCompositeScatter()`, `DMCompositeGather()` 291 @*/ 292 PetscErrorCode DMCompositeGetLocalAccessArray(DM dm, Vec pvec, PetscInt nwanted, const PetscInt wanted[], Vec vecs[]) 293 { 294 struct DMCompositeLink *link; 295 PetscInt i, wnum; 296 DM_Composite *com = (DM_Composite *)dm->data; 297 PetscInt readonly; 298 PetscInt nlocal = 0; 299 PetscBool flg; 300 301 PetscFunctionBegin; 302 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 303 PetscValidHeaderSpecific(pvec, VEC_CLASSID, 2); 304 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg)); 305 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name); 306 if (!com->setup) PetscCall(DMSetUp(dm)); 307 308 PetscCall(VecLockGet(pvec, &readonly)); 309 for (i = 0, wnum = 0, link = com->next; link && wnum < nwanted; i++, link = link->next) { 310 if (!wanted || i == wanted[wnum]) { 311 Vec v; 312 PetscCall(DMGetLocalVector(link->dm, &v)); 313 if (readonly) { 314 const PetscScalar *array; 315 PetscCall(VecGetArrayRead(pvec, &array)); 316 PetscCall(VecPlaceArray(v, array + nlocal)); 317 // this method does not make sense. The local vectors are not updated with a global-to-local and the user can not do it because it is locked 318 PetscCall(VecLockReadPush(v)); 319 PetscCall(VecRestoreArrayRead(pvec, &array)); 320 } else { 321 PetscScalar *array; 322 PetscCall(VecGetArray(pvec, &array)); 323 PetscCall(VecPlaceArray(v, array + nlocal)); 324 PetscCall(VecRestoreArray(pvec, &array)); 325 } 326 vecs[wnum++] = v; 327 } 328 329 nlocal += link->nlocal; 330 } 331 PetscFunctionReturn(PETSC_SUCCESS); 332 } 333 334 /*@C 335 DMCompositeRestoreAccess - Returns the vectors obtained with `DMCompositeGetAccess()` 336 representation. 337 338 Collective 339 340 Input Parameters: 341 + dm - the `DMCOMPOSITE` object 342 . gvec - the global vector 343 - ... - the individual parallel vectors, `NULL` for those that are not needed 344 345 Level: advanced 346 347 .seealso: `DMCOMPOSITE`, `DM`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`, 348 `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeScatter()`, 349 `DMCompositeGetAccess()` 350 @*/ 351 PetscErrorCode DMCompositeRestoreAccess(DM dm, Vec gvec, ...) 352 { 353 va_list Argp; 354 struct DMCompositeLink *next; 355 DM_Composite *com = (DM_Composite *)dm->data; 356 PetscInt readonly; 357 PetscBool flg; 358 359 PetscFunctionBegin; 360 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 361 PetscValidHeaderSpecific(gvec, VEC_CLASSID, 2); 362 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg)); 363 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name); 364 next = com->next; 365 if (!com->setup) PetscCall(DMSetUp(dm)); 366 367 PetscCall(VecLockGet(gvec, &readonly)); 368 /* loop over packed objects, handling one at a time */ 369 va_start(Argp, gvec); 370 while (next) { 371 Vec *vec; 372 vec = va_arg(Argp, Vec *); 373 if (vec) { 374 PetscCall(VecResetArray(*vec)); 375 if (readonly) PetscCall(VecLockReadPop(*vec)); 376 PetscCall(DMRestoreGlobalVector(next->dm, vec)); 377 } 378 next = next->next; 379 } 380 va_end(Argp); 381 PetscFunctionReturn(PETSC_SUCCESS); 382 } 383 384 /*@ 385 DMCompositeRestoreAccessArray - Returns the vectors obtained with `DMCompositeGetAccessArray()` 386 387 Collective 388 389 Input Parameters: 390 + dm - the `DMCOMPOSITE` object 391 . pvec - packed vector 392 . nwanted - number of vectors wanted 393 . wanted - sorted array of vectors wanted, or `NULL` to restore all vectors 394 - vecs - array of global vectors 395 396 Level: advanced 397 398 .seealso: `DMCOMPOSITE`, `DM`, `DMCompositeRestoreAccess()`, `DMCompositeRestoreEntries()`, `DMCompositeScatter()`, `DMCompositeGather()` 399 @*/ 400 PetscErrorCode DMCompositeRestoreAccessArray(DM dm, Vec pvec, PetscInt nwanted, const PetscInt wanted[], Vec vecs[]) 401 { 402 struct DMCompositeLink *link; 403 PetscInt i, wnum; 404 DM_Composite *com = (DM_Composite *)dm->data; 405 PetscInt readonly; 406 PetscBool flg; 407 408 PetscFunctionBegin; 409 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 410 PetscValidHeaderSpecific(pvec, VEC_CLASSID, 2); 411 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg)); 412 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name); 413 if (!com->setup) PetscCall(DMSetUp(dm)); 414 415 PetscCall(VecLockGet(pvec, &readonly)); 416 for (i = 0, wnum = 0, link = com->next; link && wnum < nwanted; i++, link = link->next) { 417 if (!wanted || i == wanted[wnum]) { 418 PetscCall(VecResetArray(vecs[wnum])); 419 if (readonly) PetscCall(VecLockReadPop(vecs[wnum])); 420 PetscCall(DMRestoreGlobalVector(link->dm, &vecs[wnum])); 421 wnum++; 422 } 423 } 424 PetscFunctionReturn(PETSC_SUCCESS); 425 } 426 427 /*@ 428 DMCompositeRestoreLocalAccessArray - Returns the vectors obtained with `DMCompositeGetLocalAccessArray()`. 429 430 Collective 431 432 Input Parameters: 433 + dm - the `DMCOMPOSITE` object 434 . pvec - packed vector 435 . nwanted - number of vectors wanted 436 . wanted - sorted array of vectors wanted, or `NULL` to restore all vectors 437 - vecs - array of local vectors 438 439 Level: advanced 440 441 Note: 442 `nwanted` and `wanted` must match the values given to `DMCompositeGetLocalAccessArray()` 443 otherwise the call will fail. 444 445 .seealso: `DMCOMPOSITE`, `DM`, `DMCompositeGetLocalAccessArray()`, `DMCompositeRestoreAccessArray()`, 446 `DMCompositeRestoreAccess()`, `DMCompositeRestoreEntries()`, 447 `DMCompositeScatter()`, `DMCompositeGather()` 448 @*/ 449 PetscErrorCode DMCompositeRestoreLocalAccessArray(DM dm, Vec pvec, PetscInt nwanted, const PetscInt wanted[], Vec *vecs) 450 { 451 struct DMCompositeLink *link; 452 PetscInt i, wnum; 453 DM_Composite *com = (DM_Composite *)dm->data; 454 PetscInt readonly; 455 PetscBool flg; 456 457 PetscFunctionBegin; 458 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 459 PetscValidHeaderSpecific(pvec, VEC_CLASSID, 2); 460 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg)); 461 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name); 462 if (!com->setup) PetscCall(DMSetUp(dm)); 463 464 PetscCall(VecLockGet(pvec, &readonly)); 465 for (i = 0, wnum = 0, link = com->next; link && wnum < nwanted; i++, link = link->next) { 466 if (!wanted || i == wanted[wnum]) { 467 PetscCall(VecResetArray(vecs[wnum])); 468 if (readonly) PetscCall(VecLockReadPop(vecs[wnum])); 469 PetscCall(DMRestoreLocalVector(link->dm, &vecs[wnum])); 470 wnum++; 471 } 472 } 473 PetscFunctionReturn(PETSC_SUCCESS); 474 } 475 476 /*@C 477 DMCompositeScatter - Scatters from a global packed vector into its individual local vectors 478 479 Collective 480 481 Input Parameters: 482 + dm - the `DMCOMPOSITE` object 483 . gvec - the global vector 484 - ... - the individual sequential vectors, `NULL` for those that are not needed 485 486 Level: advanced 487 488 Note: 489 `DMCompositeScatterArray()` is a non-variadic alternative that is often more convenient for library callers and is 490 accessible from Fortran. 491 492 .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`, 493 `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`, 494 `DMCompositeGetLocalVectors()`, `DMCompositeRestoreLocalVectors()`, `DMCompositeGetEntries()` 495 `DMCompositeScatterArray()` 496 @*/ 497 PetscErrorCode DMCompositeScatter(DM dm, Vec gvec, ...) 498 { 499 va_list Argp; 500 struct DMCompositeLink *next; 501 PETSC_UNUSED PetscInt cnt; 502 DM_Composite *com = (DM_Composite *)dm->data; 503 PetscBool flg; 504 505 PetscFunctionBegin; 506 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 507 PetscValidHeaderSpecific(gvec, VEC_CLASSID, 2); 508 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg)); 509 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name); 510 if (!com->setup) PetscCall(DMSetUp(dm)); 511 512 /* loop over packed objects, handling one at a time */ 513 va_start(Argp, gvec); 514 for (cnt = 3, next = com->next; next; cnt++, next = next->next) { 515 Vec local; 516 local = va_arg(Argp, Vec); 517 if (local) { 518 Vec global; 519 const PetscScalar *array; 520 PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PetscValidHeaderSpecific(local, VEC_CLASSID, (int)cnt)); 521 PetscCall(DMGetGlobalVector(next->dm, &global)); 522 PetscCall(VecGetArrayRead(gvec, &array)); 523 PetscCall(VecPlaceArray(global, array + next->rstart)); 524 PetscCall(DMGlobalToLocalBegin(next->dm, global, INSERT_VALUES, local)); 525 PetscCall(DMGlobalToLocalEnd(next->dm, global, INSERT_VALUES, local)); 526 PetscCall(VecRestoreArrayRead(gvec, &array)); 527 PetscCall(VecResetArray(global)); 528 PetscCall(DMRestoreGlobalVector(next->dm, &global)); 529 } 530 } 531 va_end(Argp); 532 PetscFunctionReturn(PETSC_SUCCESS); 533 } 534 535 /*@ 536 DMCompositeScatterArray - Scatters from a global packed vector into its individual local vectors 537 538 Collective 539 540 Input Parameters: 541 + dm - the `DMCOMPOSITE` object 542 . gvec - the global vector 543 - lvecs - array of local vectors, NULL for any that are not needed 544 545 Level: advanced 546 547 Note: 548 This is a non-variadic alternative to `DMCompositeScatter()` 549 550 .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()` 551 `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`, 552 `DMCompositeGetLocalVectors()`, `DMCompositeRestoreLocalVectors()`, `DMCompositeGetEntries()` 553 @*/ 554 PetscErrorCode DMCompositeScatterArray(DM dm, Vec gvec, Vec *lvecs) 555 { 556 struct DMCompositeLink *next; 557 PetscInt i; 558 DM_Composite *com = (DM_Composite *)dm->data; 559 PetscBool flg; 560 561 PetscFunctionBegin; 562 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 563 PetscValidHeaderSpecific(gvec, VEC_CLASSID, 2); 564 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg)); 565 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name); 566 if (!com->setup) PetscCall(DMSetUp(dm)); 567 568 /* loop over packed objects, handling one at a time */ 569 for (i = 0, next = com->next; next; next = next->next, i++) { 570 if (lvecs[i]) { 571 Vec global; 572 const PetscScalar *array; 573 PetscValidHeaderSpecific(lvecs[i], VEC_CLASSID, 3); 574 PetscCall(DMGetGlobalVector(next->dm, &global)); 575 PetscCall(VecGetArrayRead(gvec, &array)); 576 PetscCall(VecPlaceArray(global, (PetscScalar *)array + next->rstart)); 577 PetscCall(DMGlobalToLocalBegin(next->dm, global, INSERT_VALUES, lvecs[i])); 578 PetscCall(DMGlobalToLocalEnd(next->dm, global, INSERT_VALUES, lvecs[i])); 579 PetscCall(VecRestoreArrayRead(gvec, &array)); 580 PetscCall(VecResetArray(global)); 581 PetscCall(DMRestoreGlobalVector(next->dm, &global)); 582 } 583 } 584 PetscFunctionReturn(PETSC_SUCCESS); 585 } 586 587 /*@C 588 DMCompositeGather - Gathers into a global packed vector from its individual local vectors 589 590 Collective 591 592 Input Parameters: 593 + dm - the `DMCOMPOSITE` object 594 . imode - `INSERT_VALUES` or `ADD_VALUES` 595 . gvec - the global vector 596 - ... - the individual sequential vectors, `NULL` for any that are not needed 597 598 Level: advanced 599 600 Fortran Notes: 601 Fortran users should use `DMCompositeGatherArray()` 602 603 .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`, 604 `DMCompositeScatter()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`, 605 `DMCompositeGetLocalVectors()`, `DMCompositeRestoreLocalVectors()`, `DMCompositeGetEntries()` 606 @*/ 607 PetscErrorCode DMCompositeGather(DM dm, InsertMode imode, Vec gvec, ...) 608 { 609 va_list Argp; 610 struct DMCompositeLink *next; 611 DM_Composite *com = (DM_Composite *)dm->data; 612 PETSC_UNUSED PetscInt cnt; 613 PetscBool flg; 614 615 PetscFunctionBegin; 616 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 617 PetscValidHeaderSpecific(gvec, VEC_CLASSID, 3); 618 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg)); 619 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name); 620 if (!com->setup) PetscCall(DMSetUp(dm)); 621 622 /* loop over packed objects, handling one at a time */ 623 va_start(Argp, gvec); 624 for (cnt = 3, next = com->next; next; cnt++, next = next->next) { 625 Vec local; 626 local = va_arg(Argp, Vec); 627 if (local) { 628 PetscScalar *array; 629 Vec global; 630 PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PetscValidHeaderSpecific(local, VEC_CLASSID, (int)cnt)); 631 PetscCall(DMGetGlobalVector(next->dm, &global)); 632 PetscCall(VecGetArray(gvec, &array)); 633 PetscCall(VecPlaceArray(global, array + next->rstart)); 634 PetscCall(DMLocalToGlobalBegin(next->dm, local, imode, global)); 635 PetscCall(DMLocalToGlobalEnd(next->dm, local, imode, global)); 636 PetscCall(VecRestoreArray(gvec, &array)); 637 PetscCall(VecResetArray(global)); 638 PetscCall(DMRestoreGlobalVector(next->dm, &global)); 639 } 640 } 641 va_end(Argp); 642 PetscFunctionReturn(PETSC_SUCCESS); 643 } 644 645 /*@ 646 DMCompositeGatherArray - Gathers into a global packed vector from its individual local vectors 647 648 Collective 649 650 Input Parameters: 651 + dm - the `DMCOMPOSITE` object 652 . gvec - the global vector 653 . imode - `INSERT_VALUES` or `ADD_VALUES` 654 - lvecs - the individual sequential vectors, NULL for any that are not needed 655 656 Level: advanced 657 658 Note: 659 This is a non-variadic alternative to `DMCompositeGather()`. 660 661 .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`, 662 `DMCompositeScatter()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`, 663 `DMCompositeGetLocalVectors()`, `DMCompositeRestoreLocalVectors()`, `DMCompositeGetEntries()`, 664 @*/ 665 PetscErrorCode DMCompositeGatherArray(DM dm, InsertMode imode, Vec gvec, Vec *lvecs) 666 { 667 struct DMCompositeLink *next; 668 DM_Composite *com = (DM_Composite *)dm->data; 669 PetscInt i; 670 PetscBool flg; 671 672 PetscFunctionBegin; 673 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 674 PetscValidHeaderSpecific(gvec, VEC_CLASSID, 3); 675 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg)); 676 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name); 677 if (!com->setup) PetscCall(DMSetUp(dm)); 678 679 /* loop over packed objects, handling one at a time */ 680 for (next = com->next, i = 0; next; next = next->next, i++) { 681 if (lvecs[i]) { 682 PetscScalar *array; 683 Vec global; 684 PetscValidHeaderSpecific(lvecs[i], VEC_CLASSID, 4); 685 PetscCall(DMGetGlobalVector(next->dm, &global)); 686 PetscCall(VecGetArray(gvec, &array)); 687 PetscCall(VecPlaceArray(global, array + next->rstart)); 688 PetscCall(DMLocalToGlobalBegin(next->dm, lvecs[i], imode, global)); 689 PetscCall(DMLocalToGlobalEnd(next->dm, lvecs[i], imode, global)); 690 PetscCall(VecRestoreArray(gvec, &array)); 691 PetscCall(VecResetArray(global)); 692 PetscCall(DMRestoreGlobalVector(next->dm, &global)); 693 } 694 } 695 PetscFunctionReturn(PETSC_SUCCESS); 696 } 697 698 /*@ 699 DMCompositeAddDM - adds a `DM` vector to a `DMCOMPOSITE` 700 701 Collective 702 703 Input Parameters: 704 + dmc - the `DMCOMPOSITE` object 705 - dm - the `DM` object 706 707 Level: advanced 708 709 .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeGather()`, `DMCreateGlobalVector()`, 710 `DMCompositeScatter()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`, 711 `DMCompositeGetLocalVectors()`, `DMCompositeRestoreLocalVectors()`, `DMCompositeGetEntries()` 712 @*/ 713 PetscErrorCode DMCompositeAddDM(DM dmc, DM dm) 714 { 715 PetscInt n, nlocal; 716 struct DMCompositeLink *mine, *next; 717 Vec global, local; 718 DM_Composite *com = (DM_Composite *)dmc->data; 719 PetscBool flg; 720 721 PetscFunctionBegin; 722 PetscValidHeaderSpecific(dmc, DM_CLASSID, 1); 723 PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 724 PetscCall(PetscObjectTypeCompare((PetscObject)dmc, DMCOMPOSITE, &flg)); 725 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name); 726 next = com->next; 727 PetscCheck(!com->setup, PetscObjectComm((PetscObject)dmc), PETSC_ERR_ARG_WRONGSTATE, "Cannot add a DM once you have used the DMComposite"); 728 729 /* create new link */ 730 PetscCall(PetscNew(&mine)); 731 PetscCall(PetscObjectReference((PetscObject)dm)); 732 PetscCall(DMCreateGlobalVector(dm, &global)); // Not using DMGetGlobalVector() since it will stash the vector with a type decided by dm, 733 PetscCall(VecGetLocalSize(global, &n)); // while we may want to set dmc's vectype later, say via DMSetFromOptions(dmc), and we 734 PetscCall(VecDestroy(&global)); // want to propagate the type to dm. 735 PetscCall(DMCreateLocalVector(dm, &local)); // Not using DMGetLocalVector(), same reason as above. 736 PetscCall(VecGetSize(local, &nlocal)); 737 PetscCall(VecDestroy(&local)); 738 739 mine->n = n; 740 mine->nlocal = nlocal; 741 mine->dm = dm; 742 mine->next = NULL; 743 com->n += n; 744 com->nghost += nlocal; 745 746 /* add to end of list */ 747 if (!next) com->next = mine; 748 else { 749 while (next->next) next = next->next; 750 next->next = mine; 751 } 752 com->nDM++; 753 com->nmine++; 754 PetscFunctionReturn(PETSC_SUCCESS); 755 } 756 757 #include <petscdraw.h> 758 PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 759 static PetscErrorCode VecView_DMComposite(Vec gvec, PetscViewer viewer) 760 { 761 DM dm; 762 struct DMCompositeLink *next; 763 PetscBool isdraw; 764 DM_Composite *com; 765 766 PetscFunctionBegin; 767 PetscCall(VecGetDM(gvec, &dm)); 768 PetscCheck(dm, PetscObjectComm((PetscObject)gvec), PETSC_ERR_ARG_WRONG, "Vector not generated from a DMComposite"); 769 com = (DM_Composite *)dm->data; 770 next = com->next; 771 772 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 773 if (!isdraw) { 774 /* do I really want to call this? */ 775 PetscCall(VecView_MPI(gvec, viewer)); 776 } else { 777 PetscInt cnt = 0; 778 779 /* loop over packed objects, handling one at a time */ 780 while (next) { 781 Vec vec; 782 const PetscScalar *array; 783 PetscInt bs; 784 785 /* Should use VecGetSubVector() eventually, but would need to forward the DM for that to work */ 786 PetscCall(DMGetGlobalVector(next->dm, &vec)); 787 PetscCall(VecGetArrayRead(gvec, &array)); 788 PetscCall(VecPlaceArray(vec, (PetscScalar *)array + next->rstart)); 789 PetscCall(VecRestoreArrayRead(gvec, &array)); 790 PetscCall(VecView(vec, viewer)); 791 PetscCall(VecResetArray(vec)); 792 PetscCall(VecGetBlockSize(vec, &bs)); 793 PetscCall(DMRestoreGlobalVector(next->dm, &vec)); 794 PetscCall(PetscViewerDrawBaseAdd(viewer, bs)); 795 cnt += bs; 796 next = next->next; 797 } 798 PetscCall(PetscViewerDrawBaseAdd(viewer, -cnt)); 799 } 800 PetscFunctionReturn(PETSC_SUCCESS); 801 } 802 803 static PetscErrorCode DMCreateGlobalVector_Composite(DM dm, Vec *gvec) 804 { 805 DM_Composite *com = (DM_Composite *)dm->data; 806 807 PetscFunctionBegin; 808 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 809 PetscCall(DMSetFromOptions(dm)); 810 PetscCall(DMSetUp(dm)); 811 PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), gvec)); 812 PetscCall(VecSetType(*gvec, dm->vectype)); 813 PetscCall(VecSetSizes(*gvec, com->n, com->N)); 814 PetscCall(VecSetDM(*gvec, dm)); 815 PetscCall(VecSetOperation(*gvec, VECOP_VIEW, (void (*)(void))VecView_DMComposite)); 816 PetscFunctionReturn(PETSC_SUCCESS); 817 } 818 819 static PetscErrorCode DMCreateLocalVector_Composite(DM dm, Vec *lvec) 820 { 821 DM_Composite *com = (DM_Composite *)dm->data; 822 823 PetscFunctionBegin; 824 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 825 if (!com->setup) { 826 PetscCall(DMSetFromOptions(dm)); 827 PetscCall(DMSetUp(dm)); 828 } 829 PetscCall(VecCreate(PETSC_COMM_SELF, lvec)); 830 PetscCall(VecSetType(*lvec, dm->vectype)); 831 PetscCall(VecSetSizes(*lvec, com->nghost, PETSC_DECIDE)); 832 PetscCall(VecSetDM(*lvec, dm)); 833 PetscFunctionReturn(PETSC_SUCCESS); 834 } 835 836 /*@C 837 DMCompositeGetISLocalToGlobalMappings - gets an `ISLocalToGlobalMapping` for each `DM` in the `DMCOMPOSITE`, maps to the composite global space 838 839 Collective; No Fortran Support 840 841 Input Parameter: 842 . dm - the `DMCOMPOSITE` object 843 844 Output Parameter: 845 . ltogs - the individual mappings for each packed vector. Note that this includes 846 all the ghost points that individual ghosted `DMDA` may have. 847 848 Level: advanced 849 850 Note: 851 Each entry of `ltogs` should be destroyed with `ISLocalToGlobalMappingDestroy()`, `ltogs` should be freed with `PetscFree()`. 852 853 .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`, 854 `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetAccess()`, `DMCompositeScatter()`, 855 `DMCompositeGetLocalVectors()`, `DMCompositeRestoreLocalVectors()`, `DMCompositeGetEntries()` 856 @*/ 857 PetscErrorCode DMCompositeGetISLocalToGlobalMappings(DM dm, ISLocalToGlobalMapping *ltogs[]) 858 { 859 PetscInt i, *idx, n, cnt; 860 struct DMCompositeLink *next; 861 PetscMPIInt rank; 862 DM_Composite *com = (DM_Composite *)dm->data; 863 PetscBool flg; 864 865 PetscFunctionBegin; 866 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 867 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg)); 868 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name); 869 PetscCall(DMSetUp(dm)); 870 PetscCall(PetscMalloc1(com->nDM, ltogs)); 871 next = com->next; 872 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 873 874 /* loop over packed objects, handling one at a time */ 875 cnt = 0; 876 while (next) { 877 ISLocalToGlobalMapping ltog; 878 PetscMPIInt size; 879 const PetscInt *suboff, *indices; 880 Vec global; 881 882 /* Get sub-DM global indices for each local dof */ 883 PetscCall(DMGetLocalToGlobalMapping(next->dm, <og)); 884 PetscCall(ISLocalToGlobalMappingGetSize(ltog, &n)); 885 PetscCall(ISLocalToGlobalMappingGetIndices(ltog, &indices)); 886 PetscCall(PetscMalloc1(n, &idx)); 887 888 /* Get the offsets for the sub-DM global vector */ 889 PetscCall(DMGetGlobalVector(next->dm, &global)); 890 PetscCall(VecGetOwnershipRanges(global, &suboff)); 891 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)global), &size)); 892 893 /* Shift the sub-DM definition of the global space to the composite global space */ 894 for (i = 0; i < n; i++) { 895 PetscInt subi = indices[i], lo = 0, hi = size, t; 896 /* There's no consensus on what a negative index means, 897 except for skipping when setting the values in vectors and matrices */ 898 if (subi < 0) { 899 idx[i] = subi - next->grstarts[rank]; 900 continue; 901 } 902 /* Binary search to find which rank owns subi */ 903 while (hi - lo > 1) { 904 t = lo + (hi - lo) / 2; 905 if (suboff[t] > subi) hi = t; 906 else lo = t; 907 } 908 idx[i] = subi - suboff[lo] + next->grstarts[lo]; 909 } 910 PetscCall(ISLocalToGlobalMappingRestoreIndices(ltog, &indices)); 911 PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), 1, n, idx, PETSC_OWN_POINTER, &(*ltogs)[cnt])); 912 PetscCall(DMRestoreGlobalVector(next->dm, &global)); 913 next = next->next; 914 cnt++; 915 } 916 PetscFunctionReturn(PETSC_SUCCESS); 917 } 918 919 /*@C 920 DMCompositeGetLocalISs - Gets index sets for each component of a composite local vector 921 922 Not Collective; No Fortran Support 923 924 Input Parameter: 925 . dm - the `DMCOMPOSITE` 926 927 Output Parameter: 928 . is - array of serial index sets for each component of the `DMCOMPOSITE` 929 930 Level: intermediate 931 932 Notes: 933 At present, a composite local vector does not normally exist. This function is used to provide index sets for 934 `MatGetLocalSubMatrix()`. In the future, the scatters for each entry in the `DMCOMPOSITE` may be merged into a single 935 scatter to a composite local vector. The user should not typically need to know which is being done. 936 937 To get the composite global indices at all local points (including ghosts), use `DMCompositeGetISLocalToGlobalMappings()`. 938 939 To get index sets for pieces of the composite global vector, use `DMCompositeGetGlobalISs()`. 940 941 Each returned `IS` should be destroyed with `ISDestroy()`, the array should be freed with `PetscFree()`. 942 943 Fortran Note: 944 Use `DMCompositeRestoreLocalISs()` to release the `is`. 945 946 .seealso: `DMCOMPOSITE`, `DM`, `DMCompositeGetGlobalISs()`, `DMCompositeGetISLocalToGlobalMappings()`, `MatGetLocalSubMatrix()`, 947 `MatCreateLocalRef()`, `DMCompositeGetNumberDM()` 948 @*/ 949 PetscErrorCode DMCompositeGetLocalISs(DM dm, IS *is[]) 950 { 951 DM_Composite *com = (DM_Composite *)dm->data; 952 struct DMCompositeLink *link; 953 PetscInt cnt, start; 954 PetscBool flg; 955 956 PetscFunctionBegin; 957 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 958 PetscAssertPointer(is, 2); 959 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg)); 960 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name); 961 PetscCall(PetscMalloc1(com->nmine, is)); 962 for (cnt = 0, start = 0, link = com->next; link; start += link->nlocal, cnt++, link = link->next) { 963 PetscInt bs; 964 PetscCall(ISCreateStride(PETSC_COMM_SELF, link->nlocal, start, 1, &(*is)[cnt])); 965 PetscCall(DMGetBlockSize(link->dm, &bs)); 966 PetscCall(ISSetBlockSize((*is)[cnt], bs)); 967 } 968 PetscFunctionReturn(PETSC_SUCCESS); 969 } 970 971 /*@C 972 DMCompositeGetGlobalISs - Gets the index sets for each composed object in a `DMCOMPOSITE` 973 974 Collective 975 976 Input Parameter: 977 . dm - the `DMCOMPOSITE` object 978 979 Output Parameter: 980 . is - the array of index sets 981 982 Level: advanced 983 984 Notes: 985 The `is` entries should be destroyed with `ISDestroy()`, `is` should be freed with `PetscFree()` 986 987 These could be used to extract a subset of vector entries for a "multi-physics" preconditioner 988 989 Use `DMCompositeGetLocalISs()` for index sets in the packed local numbering, and 990 `DMCompositeGetISLocalToGlobalMappings()` for to map local sub-`DM` (including ghost) indices to packed global 991 indices. 992 993 Fortran Note: 994 Use `DMCompositeRestoreGlobalISs()` to release the `is`. 995 996 .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`, 997 `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetAccess()`, `DMCompositeScatter()`, 998 `DMCompositeGetLocalVectors()`, `DMCompositeRestoreLocalVectors()`, `DMCompositeGetEntries()` 999 @*/ 1000 PetscErrorCode DMCompositeGetGlobalISs(DM dm, IS *is[]) 1001 { 1002 PetscInt cnt = 0; 1003 struct DMCompositeLink *next; 1004 PetscMPIInt rank; 1005 DM_Composite *com = (DM_Composite *)dm->data; 1006 PetscBool flg; 1007 1008 PetscFunctionBegin; 1009 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1010 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg)); 1011 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name); 1012 PetscCheck(dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Must call DMSetUp() before"); 1013 PetscCall(PetscMalloc1(com->nDM, is)); 1014 next = com->next; 1015 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 1016 1017 /* loop over packed objects, handling one at a time */ 1018 while (next) { 1019 PetscDS prob; 1020 1021 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)dm), next->n, next->grstart, 1, &(*is)[cnt])); 1022 PetscCall(DMGetDS(dm, &prob)); 1023 if (prob) { 1024 MatNullSpace space; 1025 Mat pmat; 1026 PetscObject disc; 1027 PetscInt Nf; 1028 1029 PetscCall(PetscDSGetNumFields(prob, &Nf)); 1030 if (cnt < Nf) { 1031 PetscCall(PetscDSGetDiscretization(prob, cnt, &disc)); 1032 PetscCall(PetscObjectQuery(disc, "nullspace", (PetscObject *)&space)); 1033 if (space) PetscCall(PetscObjectCompose((PetscObject)(*is)[cnt], "nullspace", (PetscObject)space)); 1034 PetscCall(PetscObjectQuery(disc, "nearnullspace", (PetscObject *)&space)); 1035 if (space) PetscCall(PetscObjectCompose((PetscObject)(*is)[cnt], "nearnullspace", (PetscObject)space)); 1036 PetscCall(PetscObjectQuery(disc, "pmat", (PetscObject *)&pmat)); 1037 if (pmat) PetscCall(PetscObjectCompose((PetscObject)(*is)[cnt], "pmat", (PetscObject)pmat)); 1038 } 1039 } 1040 cnt++; 1041 next = next->next; 1042 } 1043 PetscFunctionReturn(PETSC_SUCCESS); 1044 } 1045 1046 static PetscErrorCode DMCreateFieldIS_Composite(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields) 1047 { 1048 PetscInt nDM; 1049 DM *dms; 1050 PetscInt i; 1051 1052 PetscFunctionBegin; 1053 PetscCall(DMCompositeGetNumberDM(dm, &nDM)); 1054 if (numFields) *numFields = nDM; 1055 PetscCall(DMCompositeGetGlobalISs(dm, fields)); 1056 if (fieldNames) { 1057 PetscCall(PetscMalloc1(nDM, &dms)); 1058 PetscCall(PetscMalloc1(nDM, fieldNames)); 1059 PetscCall(DMCompositeGetEntriesArray(dm, dms)); 1060 for (i = 0; i < nDM; i++) { 1061 char buf[256]; 1062 const char *splitname; 1063 1064 /* Split naming precedence: object name, prefix, number */ 1065 splitname = ((PetscObject)dm)->name; 1066 if (!splitname) { 1067 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dms[i], &splitname)); 1068 if (splitname) { 1069 size_t len; 1070 PetscCall(PetscStrncpy(buf, splitname, sizeof(buf))); 1071 buf[sizeof(buf) - 1] = 0; 1072 PetscCall(PetscStrlen(buf, &len)); 1073 if (buf[len - 1] == '_') buf[len - 1] = 0; /* Remove trailing underscore if it was used */ 1074 splitname = buf; 1075 } 1076 } 1077 if (!splitname) { 1078 PetscCall(PetscSNPrintf(buf, sizeof(buf), "%" PetscInt_FMT, i)); 1079 splitname = buf; 1080 } 1081 PetscCall(PetscStrallocpy(splitname, &(*fieldNames)[i])); 1082 } 1083 PetscCall(PetscFree(dms)); 1084 } 1085 PetscFunctionReturn(PETSC_SUCCESS); 1086 } 1087 1088 /* 1089 This could take over from DMCreateFieldIS(), as it is more general, 1090 making DMCreateFieldIS() a special case -- calling with dmlist == NULL; 1091 At this point it's probably best to be less intrusive, however. 1092 */ 1093 static PetscErrorCode DMCreateFieldDecomposition_Composite(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist) 1094 { 1095 PetscInt nDM; 1096 PetscInt i; 1097 1098 PetscFunctionBegin; 1099 PetscCall(DMCreateFieldIS_Composite(dm, len, namelist, islist)); 1100 if (dmlist) { 1101 PetscCall(DMCompositeGetNumberDM(dm, &nDM)); 1102 PetscCall(PetscMalloc1(nDM, dmlist)); 1103 PetscCall(DMCompositeGetEntriesArray(dm, *dmlist)); 1104 for (i = 0; i < nDM; i++) PetscCall(PetscObjectReference((PetscObject)((*dmlist)[i]))); 1105 } 1106 PetscFunctionReturn(PETSC_SUCCESS); 1107 } 1108 1109 /*@C 1110 DMCompositeGetLocalVectors - Gets local vectors for each part of a `DMCOMPOSITE` 1111 Use `DMCompositeRestoreLocalVectors()` to return them. 1112 1113 Not Collective; No Fortran Support 1114 1115 Input Parameter: 1116 . dm - the `DMCOMPOSITE` object 1117 1118 Output Parameter: 1119 . ... - the individual sequential `Vec`s 1120 1121 Level: advanced 1122 1123 .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`, 1124 `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`, 1125 `DMCompositeRestoreLocalVectors()`, `DMCompositeScatter()`, `DMCompositeGetEntries()` 1126 @*/ 1127 PetscErrorCode DMCompositeGetLocalVectors(DM dm, ...) 1128 { 1129 va_list Argp; 1130 struct DMCompositeLink *next; 1131 DM_Composite *com = (DM_Composite *)dm->data; 1132 PetscBool flg; 1133 1134 PetscFunctionBegin; 1135 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1136 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg)); 1137 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name); 1138 next = com->next; 1139 /* loop over packed objects, handling one at a time */ 1140 va_start(Argp, dm); 1141 while (next) { 1142 Vec *vec; 1143 vec = va_arg(Argp, Vec *); 1144 if (vec) PetscCall(DMGetLocalVector(next->dm, vec)); 1145 next = next->next; 1146 } 1147 va_end(Argp); 1148 PetscFunctionReturn(PETSC_SUCCESS); 1149 } 1150 1151 /*@C 1152 DMCompositeRestoreLocalVectors - Restores local vectors for each part of a `DMCOMPOSITE` 1153 1154 Not Collective; No Fortran Support 1155 1156 Input Parameter: 1157 . dm - the `DMCOMPOSITE` object 1158 1159 Output Parameter: 1160 . ... - the individual sequential `Vec` 1161 1162 Level: advanced 1163 1164 .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`, 1165 `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`, 1166 `DMCompositeGetLocalVectors()`, `DMCompositeScatter()`, `DMCompositeGetEntries()` 1167 @*/ 1168 PetscErrorCode DMCompositeRestoreLocalVectors(DM dm, ...) 1169 { 1170 va_list Argp; 1171 struct DMCompositeLink *next; 1172 DM_Composite *com = (DM_Composite *)dm->data; 1173 PetscBool flg; 1174 1175 PetscFunctionBegin; 1176 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1177 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg)); 1178 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name); 1179 next = com->next; 1180 /* loop over packed objects, handling one at a time */ 1181 va_start(Argp, dm); 1182 while (next) { 1183 Vec *vec; 1184 vec = va_arg(Argp, Vec *); 1185 if (vec) PetscCall(DMRestoreLocalVector(next->dm, vec)); 1186 next = next->next; 1187 } 1188 va_end(Argp); 1189 PetscFunctionReturn(PETSC_SUCCESS); 1190 } 1191 1192 /*@C 1193 DMCompositeGetEntries - Gets the `DM` for each entry in a `DMCOMPOSITE`. 1194 1195 Not Collective 1196 1197 Input Parameter: 1198 . dm - the `DMCOMPOSITE` object 1199 1200 Output Parameter: 1201 . ... - the individual entries `DM` 1202 1203 Level: advanced 1204 1205 Fortran Notes: 1206 Use `DMCompositeGetEntriesArray()` 1207 1208 .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`, `DMCompositeGetEntriesArray()` 1209 `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`, 1210 `DMCompositeRestoreLocalVectors()`, `DMCompositeGetLocalVectors()`, `DMCompositeScatter()` 1211 @*/ 1212 PetscErrorCode DMCompositeGetEntries(DM dm, ...) 1213 { 1214 va_list Argp; 1215 struct DMCompositeLink *next; 1216 DM_Composite *com = (DM_Composite *)dm->data; 1217 PetscBool flg; 1218 1219 PetscFunctionBegin; 1220 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1221 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg)); 1222 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name); 1223 next = com->next; 1224 /* loop over packed objects, handling one at a time */ 1225 va_start(Argp, dm); 1226 while (next) { 1227 DM *dmn; 1228 dmn = va_arg(Argp, DM *); 1229 if (dmn) *dmn = next->dm; 1230 next = next->next; 1231 } 1232 va_end(Argp); 1233 PetscFunctionReturn(PETSC_SUCCESS); 1234 } 1235 1236 /*@ 1237 DMCompositeGetEntriesArray - Gets the DM for each entry in a `DMCOMPOSITE` 1238 1239 Not Collective 1240 1241 Input Parameter: 1242 . dm - the `DMCOMPOSITE` object 1243 1244 Output Parameter: 1245 . dms - array of sufficient length (see `DMCompositeGetNumberDM()`) to hold the individual `DM` 1246 1247 Level: advanced 1248 1249 .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`, `DMCompositeGetEntries()` 1250 `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`, 1251 `DMCompositeRestoreLocalVectors()`, `DMCompositeGetLocalVectors()`, `DMCompositeScatter()` 1252 @*/ 1253 PetscErrorCode DMCompositeGetEntriesArray(DM dm, DM dms[]) 1254 { 1255 struct DMCompositeLink *next; 1256 DM_Composite *com = (DM_Composite *)dm->data; 1257 PetscInt i; 1258 PetscBool flg; 1259 1260 PetscFunctionBegin; 1261 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1262 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg)); 1263 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name); 1264 /* loop over packed objects, handling one at a time */ 1265 for (next = com->next, i = 0; next; next = next->next, i++) dms[i] = next->dm; 1266 PetscFunctionReturn(PETSC_SUCCESS); 1267 } 1268 1269 typedef struct { 1270 DM dm; 1271 PetscViewer *subv; 1272 Vec *vecs; 1273 } GLVisViewerCtx; 1274 1275 static PetscErrorCode DestroyGLVisViewerCtx_Private(void *vctx) 1276 { 1277 GLVisViewerCtx *ctx = (GLVisViewerCtx *)vctx; 1278 PetscInt i, n; 1279 1280 PetscFunctionBegin; 1281 PetscCall(DMCompositeGetNumberDM(ctx->dm, &n)); 1282 for (i = 0; i < n; i++) PetscCall(PetscViewerDestroy(&ctx->subv[i])); 1283 PetscCall(PetscFree2(ctx->subv, ctx->vecs)); 1284 PetscCall(DMDestroy(&ctx->dm)); 1285 PetscCall(PetscFree(ctx)); 1286 PetscFunctionReturn(PETSC_SUCCESS); 1287 } 1288 1289 static PetscErrorCode DMCompositeSampleGLVisFields_Private(PetscObject oX, PetscInt nf, PetscObject oXfield[], void *vctx) 1290 { 1291 Vec X = (Vec)oX; 1292 GLVisViewerCtx *ctx = (GLVisViewerCtx *)vctx; 1293 PetscInt i, n, cumf; 1294 1295 PetscFunctionBegin; 1296 PetscCall(DMCompositeGetNumberDM(ctx->dm, &n)); 1297 PetscCall(DMCompositeGetAccessArray(ctx->dm, X, n, NULL, ctx->vecs)); 1298 for (i = 0, cumf = 0; i < n; i++) { 1299 PetscErrorCode (*g2l)(PetscObject, PetscInt, PetscObject[], void *); 1300 void *fctx; 1301 PetscInt nfi; 1302 1303 PetscCall(PetscViewerGLVisGetFields_Internal(ctx->subv[i], &nfi, NULL, NULL, &g2l, NULL, &fctx)); 1304 if (!nfi) continue; 1305 if (g2l) PetscCall((*g2l)((PetscObject)ctx->vecs[i], nfi, oXfield + cumf, fctx)); 1306 else PetscCall(VecCopy(ctx->vecs[i], (Vec)oXfield[cumf])); 1307 cumf += nfi; 1308 } 1309 PetscCall(DMCompositeRestoreAccessArray(ctx->dm, X, n, NULL, ctx->vecs)); 1310 PetscFunctionReturn(PETSC_SUCCESS); 1311 } 1312 1313 static PetscErrorCode DMSetUpGLVisViewer_Composite(PetscObject odm, PetscViewer viewer) 1314 { 1315 DM dm = (DM)odm, *dms; 1316 Vec *Ufds; 1317 GLVisViewerCtx *ctx; 1318 PetscInt i, n, tnf, *sdim; 1319 char **fecs; 1320 1321 PetscFunctionBegin; 1322 PetscCall(PetscNew(&ctx)); 1323 PetscCall(PetscObjectReference((PetscObject)dm)); 1324 ctx->dm = dm; 1325 PetscCall(DMCompositeGetNumberDM(dm, &n)); 1326 PetscCall(PetscMalloc1(n, &dms)); 1327 PetscCall(DMCompositeGetEntriesArray(dm, dms)); 1328 PetscCall(PetscMalloc2(n, &ctx->subv, n, &ctx->vecs)); 1329 for (i = 0, tnf = 0; i < n; i++) { 1330 PetscInt nf; 1331 1332 PetscCall(PetscViewerCreate(PetscObjectComm(odm), &ctx->subv[i])); 1333 PetscCall(PetscViewerSetType(ctx->subv[i], PETSCVIEWERGLVIS)); 1334 PetscCall(PetscViewerGLVisSetDM_Internal(ctx->subv[i], (PetscObject)dms[i])); 1335 PetscCall(PetscViewerGLVisGetFields_Internal(ctx->subv[i], &nf, NULL, NULL, NULL, NULL, NULL)); 1336 tnf += nf; 1337 } 1338 PetscCall(PetscFree(dms)); 1339 PetscCall(PetscMalloc3(tnf, &fecs, tnf, &sdim, tnf, &Ufds)); 1340 for (i = 0, tnf = 0; i < n; i++) { 1341 PetscInt *sd, nf, f; 1342 const char **fec; 1343 Vec *Uf; 1344 1345 PetscCall(PetscViewerGLVisGetFields_Internal(ctx->subv[i], &nf, &fec, &sd, NULL, (PetscObject **)&Uf, NULL)); 1346 for (f = 0; f < nf; f++) { 1347 PetscCall(PetscStrallocpy(fec[f], &fecs[tnf + f])); 1348 Ufds[tnf + f] = Uf[f]; 1349 sdim[tnf + f] = sd[f]; 1350 } 1351 tnf += nf; 1352 } 1353 PetscCall(PetscViewerGLVisSetFields(viewer, tnf, (const char **)fecs, sdim, DMCompositeSampleGLVisFields_Private, (PetscObject *)Ufds, ctx, DestroyGLVisViewerCtx_Private)); 1354 for (i = 0; i < tnf; i++) PetscCall(PetscFree(fecs[i])); 1355 PetscCall(PetscFree3(fecs, sdim, Ufds)); 1356 PetscFunctionReturn(PETSC_SUCCESS); 1357 } 1358 1359 static PetscErrorCode DMRefine_Composite(DM dmi, MPI_Comm comm, DM *fine) 1360 { 1361 struct DMCompositeLink *next; 1362 DM_Composite *com = (DM_Composite *)dmi->data; 1363 DM dm; 1364 1365 PetscFunctionBegin; 1366 PetscValidHeaderSpecific(dmi, DM_CLASSID, 1); 1367 if (comm == MPI_COMM_NULL) PetscCall(PetscObjectGetComm((PetscObject)dmi, &comm)); 1368 PetscCall(DMSetUp(dmi)); 1369 next = com->next; 1370 PetscCall(DMCompositeCreate(comm, fine)); 1371 1372 /* loop over packed objects, handling one at a time */ 1373 while (next) { 1374 PetscCall(DMRefine(next->dm, comm, &dm)); 1375 PetscCall(DMCompositeAddDM(*fine, dm)); 1376 PetscCall(PetscObjectDereference((PetscObject)dm)); 1377 next = next->next; 1378 } 1379 PetscFunctionReturn(PETSC_SUCCESS); 1380 } 1381 1382 static PetscErrorCode DMCoarsen_Composite(DM dmi, MPI_Comm comm, DM *fine) 1383 { 1384 struct DMCompositeLink *next; 1385 DM_Composite *com = (DM_Composite *)dmi->data; 1386 DM dm; 1387 1388 PetscFunctionBegin; 1389 PetscValidHeaderSpecific(dmi, DM_CLASSID, 1); 1390 PetscCall(DMSetUp(dmi)); 1391 if (comm == MPI_COMM_NULL) PetscCall(PetscObjectGetComm((PetscObject)dmi, &comm)); 1392 next = com->next; 1393 PetscCall(DMCompositeCreate(comm, fine)); 1394 1395 /* loop over packed objects, handling one at a time */ 1396 while (next) { 1397 PetscCall(DMCoarsen(next->dm, comm, &dm)); 1398 PetscCall(DMCompositeAddDM(*fine, dm)); 1399 PetscCall(PetscObjectDereference((PetscObject)dm)); 1400 next = next->next; 1401 } 1402 PetscFunctionReturn(PETSC_SUCCESS); 1403 } 1404 1405 static PetscErrorCode DMCreateInterpolation_Composite(DM coarse, DM fine, Mat *A, Vec *v) 1406 { 1407 PetscInt m, n, M, N, nDM, i; 1408 struct DMCompositeLink *nextc; 1409 struct DMCompositeLink *nextf; 1410 Vec gcoarse, gfine, *vecs; 1411 DM_Composite *comcoarse = (DM_Composite *)coarse->data; 1412 DM_Composite *comfine = (DM_Composite *)fine->data; 1413 Mat *mats; 1414 1415 PetscFunctionBegin; 1416 PetscValidHeaderSpecific(coarse, DM_CLASSID, 1); 1417 PetscValidHeaderSpecific(fine, DM_CLASSID, 2); 1418 PetscCall(DMSetUp(coarse)); 1419 PetscCall(DMSetUp(fine)); 1420 /* use global vectors only for determining matrix layout */ 1421 PetscCall(DMGetGlobalVector(coarse, &gcoarse)); 1422 PetscCall(DMGetGlobalVector(fine, &gfine)); 1423 PetscCall(VecGetLocalSize(gcoarse, &n)); 1424 PetscCall(VecGetLocalSize(gfine, &m)); 1425 PetscCall(VecGetSize(gcoarse, &N)); 1426 PetscCall(VecGetSize(gfine, &M)); 1427 PetscCall(DMRestoreGlobalVector(coarse, &gcoarse)); 1428 PetscCall(DMRestoreGlobalVector(fine, &gfine)); 1429 1430 nDM = comfine->nDM; 1431 PetscCheck(nDM == comcoarse->nDM, PetscObjectComm((PetscObject)fine), PETSC_ERR_ARG_INCOMP, "Fine DMComposite has %" PetscInt_FMT " entries, but coarse has %" PetscInt_FMT, nDM, comcoarse->nDM); 1432 PetscCall(PetscCalloc1(nDM * nDM, &mats)); 1433 if (v) PetscCall(PetscCalloc1(nDM, &vecs)); 1434 1435 /* loop over packed objects, handling one at a time */ 1436 for (nextc = comcoarse->next, nextf = comfine->next, i = 0; nextc; nextc = nextc->next, nextf = nextf->next, i++) { 1437 if (!v) PetscCall(DMCreateInterpolation(nextc->dm, nextf->dm, &mats[i * nDM + i], NULL)); 1438 else PetscCall(DMCreateInterpolation(nextc->dm, nextf->dm, &mats[i * nDM + i], &vecs[i])); 1439 } 1440 PetscCall(MatCreateNest(PetscObjectComm((PetscObject)fine), nDM, NULL, nDM, NULL, mats, A)); 1441 if (v) PetscCall(VecCreateNest(PetscObjectComm((PetscObject)fine), nDM, NULL, vecs, v)); 1442 for (i = 0; i < nDM * nDM; i++) PetscCall(MatDestroy(&mats[i])); 1443 PetscCall(PetscFree(mats)); 1444 if (v) { 1445 for (i = 0; i < nDM; i++) PetscCall(VecDestroy(&vecs[i])); 1446 PetscCall(PetscFree(vecs)); 1447 } 1448 PetscFunctionReturn(PETSC_SUCCESS); 1449 } 1450 1451 static PetscErrorCode DMGetLocalToGlobalMapping_Composite(DM dm) 1452 { 1453 DM_Composite *com = (DM_Composite *)dm->data; 1454 ISLocalToGlobalMapping *ltogs; 1455 PetscInt i; 1456 1457 PetscFunctionBegin; 1458 /* Set the ISLocalToGlobalMapping on the new matrix */ 1459 PetscCall(DMCompositeGetISLocalToGlobalMappings(dm, <ogs)); 1460 PetscCall(ISLocalToGlobalMappingConcatenate(PetscObjectComm((PetscObject)dm), com->nDM, ltogs, &dm->ltogmap)); 1461 for (i = 0; i < com->nDM; i++) PetscCall(ISLocalToGlobalMappingDestroy(<ogs[i])); 1462 PetscCall(PetscFree(ltogs)); 1463 PetscFunctionReturn(PETSC_SUCCESS); 1464 } 1465 1466 static PetscErrorCode DMCreateColoring_Composite(DM dm, ISColoringType ctype, ISColoring *coloring) 1467 { 1468 PetscInt n, i, cnt; 1469 ISColoringValue *colors; 1470 PetscBool dense = PETSC_FALSE; 1471 ISColoringValue maxcol = 0; 1472 DM_Composite *com = (DM_Composite *)dm->data; 1473 1474 PetscFunctionBegin; 1475 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1476 PetscCheck(ctype != IS_COLORING_LOCAL, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only global coloring supported"); 1477 if (ctype == IS_COLORING_GLOBAL) { 1478 n = com->n; 1479 } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Unknown ISColoringType"); 1480 PetscCall(PetscMalloc1(n, &colors)); /* freed in ISColoringDestroy() */ 1481 1482 PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dmcomposite_dense_jacobian", &dense, NULL)); 1483 if (dense) { 1484 PetscCall(ISColoringValueCast(com->N, &maxcol)); 1485 for (i = 0; i < n; i++) PetscCall(ISColoringValueCast(com->rstart + i, colors + i)); 1486 } else { 1487 struct DMCompositeLink *next = com->next; 1488 PetscMPIInt rank; 1489 1490 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 1491 cnt = 0; 1492 while (next) { 1493 ISColoring lcoloring; 1494 1495 PetscCall(DMCreateColoring(next->dm, IS_COLORING_GLOBAL, &lcoloring)); 1496 for (i = 0; i < lcoloring->N; i++) PetscCall(ISColoringValueCast(maxcol + lcoloring->colors[i], colors + cnt++)); 1497 maxcol += lcoloring->n; 1498 PetscCall(ISColoringDestroy(&lcoloring)); 1499 next = next->next; 1500 } 1501 } 1502 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)dm), maxcol, n, colors, PETSC_OWN_POINTER, coloring)); 1503 PetscFunctionReturn(PETSC_SUCCESS); 1504 } 1505 1506 static PetscErrorCode DMGlobalToLocalBegin_Composite(DM dm, Vec gvec, InsertMode mode, Vec lvec) 1507 { 1508 struct DMCompositeLink *next; 1509 PetscScalar *garray, *larray; 1510 DM_Composite *com = (DM_Composite *)dm->data; 1511 1512 PetscFunctionBegin; 1513 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1514 PetscValidHeaderSpecific(gvec, VEC_CLASSID, 2); 1515 1516 if (!com->setup) PetscCall(DMSetUp(dm)); 1517 1518 PetscCall(VecGetArray(gvec, &garray)); 1519 PetscCall(VecGetArray(lvec, &larray)); 1520 1521 /* loop over packed objects, handling one at a time */ 1522 next = com->next; 1523 while (next) { 1524 Vec local, global; 1525 PetscInt N; 1526 1527 PetscCall(DMGetGlobalVector(next->dm, &global)); 1528 PetscCall(VecGetLocalSize(global, &N)); 1529 PetscCall(VecPlaceArray(global, garray)); 1530 PetscCall(DMGetLocalVector(next->dm, &local)); 1531 PetscCall(VecPlaceArray(local, larray)); 1532 PetscCall(DMGlobalToLocalBegin(next->dm, global, mode, local)); 1533 PetscCall(DMGlobalToLocalEnd(next->dm, global, mode, local)); 1534 PetscCall(VecResetArray(global)); 1535 PetscCall(VecResetArray(local)); 1536 PetscCall(DMRestoreGlobalVector(next->dm, &global)); 1537 PetscCall(DMRestoreLocalVector(next->dm, &local)); 1538 1539 larray += next->nlocal; 1540 garray += next->n; 1541 next = next->next; 1542 } 1543 1544 PetscCall(VecRestoreArray(gvec, NULL)); 1545 PetscCall(VecRestoreArray(lvec, NULL)); 1546 PetscFunctionReturn(PETSC_SUCCESS); 1547 } 1548 1549 static PetscErrorCode DMGlobalToLocalEnd_Composite(DM dm, Vec gvec, InsertMode mode, Vec lvec) 1550 { 1551 PetscFunctionBegin; 1552 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1553 PetscValidHeaderSpecific(gvec, VEC_CLASSID, 2); 1554 PetscValidHeaderSpecific(lvec, VEC_CLASSID, 4); 1555 PetscFunctionReturn(PETSC_SUCCESS); 1556 } 1557 1558 static PetscErrorCode DMLocalToGlobalBegin_Composite(DM dm, Vec lvec, InsertMode mode, Vec gvec) 1559 { 1560 struct DMCompositeLink *next; 1561 PetscScalar *larray, *garray; 1562 DM_Composite *com = (DM_Composite *)dm->data; 1563 1564 PetscFunctionBegin; 1565 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1566 PetscValidHeaderSpecific(lvec, VEC_CLASSID, 2); 1567 PetscValidHeaderSpecific(gvec, VEC_CLASSID, 4); 1568 1569 if (!com->setup) PetscCall(DMSetUp(dm)); 1570 1571 PetscCall(VecGetArray(lvec, &larray)); 1572 PetscCall(VecGetArray(gvec, &garray)); 1573 1574 /* loop over packed objects, handling one at a time */ 1575 next = com->next; 1576 while (next) { 1577 Vec global, local; 1578 1579 PetscCall(DMGetLocalVector(next->dm, &local)); 1580 PetscCall(VecPlaceArray(local, larray)); 1581 PetscCall(DMGetGlobalVector(next->dm, &global)); 1582 PetscCall(VecPlaceArray(global, garray)); 1583 PetscCall(DMLocalToGlobalBegin(next->dm, local, mode, global)); 1584 PetscCall(DMLocalToGlobalEnd(next->dm, local, mode, global)); 1585 PetscCall(VecResetArray(local)); 1586 PetscCall(VecResetArray(global)); 1587 PetscCall(DMRestoreGlobalVector(next->dm, &global)); 1588 PetscCall(DMRestoreLocalVector(next->dm, &local)); 1589 1590 garray += next->n; 1591 larray += next->nlocal; 1592 next = next->next; 1593 } 1594 1595 PetscCall(VecRestoreArray(gvec, NULL)); 1596 PetscCall(VecRestoreArray(lvec, NULL)); 1597 PetscFunctionReturn(PETSC_SUCCESS); 1598 } 1599 1600 static PetscErrorCode DMLocalToGlobalEnd_Composite(DM dm, Vec lvec, InsertMode mode, Vec gvec) 1601 { 1602 PetscFunctionBegin; 1603 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1604 PetscValidHeaderSpecific(lvec, VEC_CLASSID, 2); 1605 PetscValidHeaderSpecific(gvec, VEC_CLASSID, 4); 1606 PetscFunctionReturn(PETSC_SUCCESS); 1607 } 1608 1609 static PetscErrorCode DMLocalToLocalBegin_Composite(DM dm, Vec vec1, InsertMode mode, Vec vec2) 1610 { 1611 struct DMCompositeLink *next; 1612 PetscScalar *array1, *array2; 1613 DM_Composite *com = (DM_Composite *)dm->data; 1614 1615 PetscFunctionBegin; 1616 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1617 PetscValidHeaderSpecific(vec1, VEC_CLASSID, 2); 1618 PetscValidHeaderSpecific(vec2, VEC_CLASSID, 4); 1619 1620 if (!com->setup) PetscCall(DMSetUp(dm)); 1621 1622 PetscCall(VecGetArray(vec1, &array1)); 1623 PetscCall(VecGetArray(vec2, &array2)); 1624 1625 /* loop over packed objects, handling one at a time */ 1626 next = com->next; 1627 while (next) { 1628 Vec local1, local2; 1629 1630 PetscCall(DMGetLocalVector(next->dm, &local1)); 1631 PetscCall(VecPlaceArray(local1, array1)); 1632 PetscCall(DMGetLocalVector(next->dm, &local2)); 1633 PetscCall(VecPlaceArray(local2, array2)); 1634 PetscCall(DMLocalToLocalBegin(next->dm, local1, mode, local2)); 1635 PetscCall(DMLocalToLocalEnd(next->dm, local1, mode, local2)); 1636 PetscCall(VecResetArray(local2)); 1637 PetscCall(DMRestoreLocalVector(next->dm, &local2)); 1638 PetscCall(VecResetArray(local1)); 1639 PetscCall(DMRestoreLocalVector(next->dm, &local1)); 1640 1641 array1 += next->nlocal; 1642 array2 += next->nlocal; 1643 next = next->next; 1644 } 1645 1646 PetscCall(VecRestoreArray(vec1, NULL)); 1647 PetscCall(VecRestoreArray(vec2, NULL)); 1648 PetscFunctionReturn(PETSC_SUCCESS); 1649 } 1650 1651 static PetscErrorCode DMLocalToLocalEnd_Composite(DM dm, Vec lvec, InsertMode mode, Vec gvec) 1652 { 1653 PetscFunctionBegin; 1654 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1655 PetscValidHeaderSpecific(lvec, VEC_CLASSID, 2); 1656 PetscValidHeaderSpecific(gvec, VEC_CLASSID, 4); 1657 PetscFunctionReturn(PETSC_SUCCESS); 1658 } 1659 1660 /*MC 1661 DMCOMPOSITE = "composite" - A `DM` object that is used to manage data for a collection of `DM` 1662 1663 Level: intermediate 1664 1665 .seealso: `DMType`, `DM`, `DMDACreate()`, `DMCreate()`, `DMSetType()`, `DMCompositeCreate()` 1666 M*/ 1667 1668 PETSC_EXTERN PetscErrorCode DMCreate_Composite(DM p) 1669 { 1670 DM_Composite *com; 1671 1672 PetscFunctionBegin; 1673 PetscCall(PetscNew(&com)); 1674 p->data = com; 1675 com->n = 0; 1676 com->nghost = 0; 1677 com->next = NULL; 1678 com->nDM = 0; 1679 1680 p->ops->createglobalvector = DMCreateGlobalVector_Composite; 1681 p->ops->createlocalvector = DMCreateLocalVector_Composite; 1682 p->ops->getlocaltoglobalmapping = DMGetLocalToGlobalMapping_Composite; 1683 p->ops->createfieldis = DMCreateFieldIS_Composite; 1684 p->ops->createfielddecomposition = DMCreateFieldDecomposition_Composite; 1685 p->ops->refine = DMRefine_Composite; 1686 p->ops->coarsen = DMCoarsen_Composite; 1687 p->ops->createinterpolation = DMCreateInterpolation_Composite; 1688 p->ops->creatematrix = DMCreateMatrix_Composite; 1689 p->ops->getcoloring = DMCreateColoring_Composite; 1690 p->ops->globaltolocalbegin = DMGlobalToLocalBegin_Composite; 1691 p->ops->globaltolocalend = DMGlobalToLocalEnd_Composite; 1692 p->ops->localtoglobalbegin = DMLocalToGlobalBegin_Composite; 1693 p->ops->localtoglobalend = DMLocalToGlobalEnd_Composite; 1694 p->ops->localtolocalbegin = DMLocalToLocalBegin_Composite; 1695 p->ops->localtolocalend = DMLocalToLocalEnd_Composite; 1696 p->ops->destroy = DMDestroy_Composite; 1697 p->ops->view = DMView_Composite; 1698 p->ops->setup = DMSetUp_Composite; 1699 1700 PetscCall(PetscObjectComposeFunction((PetscObject)p, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Composite)); 1701 PetscFunctionReturn(PETSC_SUCCESS); 1702 } 1703 1704 /*@ 1705 DMCompositeCreate - Creates a `DMCOMPOSITE`, used to generate "composite" 1706 vectors made up of several subvectors. 1707 1708 Collective 1709 1710 Input Parameter: 1711 . comm - the processors that will share the global vector 1712 1713 Output Parameter: 1714 . packer - the `DMCOMPOSITE` object 1715 1716 Level: advanced 1717 1718 .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCompositeScatter()`, `DMCreate()` 1719 `DMCompositeGather()`, `DMCreateGlobalVector()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()` 1720 `DMCompositeGetLocalVectors()`, `DMCompositeRestoreLocalVectors()`, `DMCompositeGetEntries()` 1721 @*/ 1722 PetscErrorCode DMCompositeCreate(MPI_Comm comm, DM *packer) 1723 { 1724 PetscFunctionBegin; 1725 PetscAssertPointer(packer, 2); 1726 PetscCall(DMCreate(comm, packer)); 1727 PetscCall(DMSetType(*packer, DMCOMPOSITE)); 1728 PetscFunctionReturn(PETSC_SUCCESS); 1729 } 1730