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