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