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