1 #include <petscsnes.h> 2 #include <petsc-private/dmimpl.h> /*I "petscdm.h" I*/ 3 4 PetscClassId DM_CLASSID; 5 PetscLogEvent DM_Convert, DM_GlobalToLocal, DM_LocalToGlobal; 6 7 #undef __FUNCT__ 8 #define __FUNCT__ "DMCreate" 9 /*@ 10 DMCreate - Creates an empty DM object. The type can then be set with DMSetType(). 11 12 If you never call DMSetType() it will generate an 13 error when you try to use the vector. 14 15 Collective on MPI_Comm 16 17 Input Parameter: 18 . comm - The communicator for the DM object 19 20 Output Parameter: 21 . dm - The DM object 22 23 Level: beginner 24 25 .seealso: DMSetType(), DMDA, DMSLICED, DMCOMPOSITE 26 @*/ 27 PetscErrorCode DMCreate(MPI_Comm comm,DM *dm) 28 { 29 DM v; 30 PetscErrorCode ierr; 31 32 PetscFunctionBegin; 33 PetscValidPointer(dm,2); 34 *dm = PETSC_NULL; 35 #ifndef PETSC_USE_DYNAMIC_LIBRARIES 36 ierr = VecInitializePackage(PETSC_NULL);CHKERRQ(ierr); 37 ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr); 38 ierr = DMInitializePackage(PETSC_NULL);CHKERRQ(ierr); 39 #endif 40 41 ierr = PetscHeaderCreate(v, _p_DM, struct _DMOps, DM_CLASSID, -1, "DM", "Distribution Manager", "DM", comm, DMDestroy, DMView);CHKERRQ(ierr); 42 ierr = PetscMemzero(v->ops, sizeof(struct _DMOps));CHKERRQ(ierr); 43 44 45 v->ltogmap = PETSC_NULL; 46 v->ltogmapb = PETSC_NULL; 47 v->bs = 1; 48 v->coloringtype = IS_COLORING_GLOBAL; 49 v->lf = PETSC_NULL; 50 v->lj = PETSC_NULL; 51 ierr = PetscSFCreate(comm, &v->sf);CHKERRQ(ierr); 52 ierr = PetscSFCreate(comm, &v->defaultSF);CHKERRQ(ierr); 53 v->defaultSection = PETSC_NULL; 54 v->defaultGlobalSection = PETSC_NULL; 55 { 56 PetscInt i; 57 for(i = 0; i < 10; ++i) { 58 v->nullspaceConstructors[i] = PETSC_NULL; 59 } 60 } 61 v->numFields = 0; 62 v->fields = PETSC_NULL; 63 64 *dm = v; 65 PetscFunctionReturn(0); 66 } 67 68 69 #undef __FUNCT__ 70 #define __FUNCT__ "DMSetVecType" 71 /*@C 72 DMSetVecType - Sets the type of vector created with DMCreateLocalVector() and DMCreateGlobalVector() 73 74 Logically Collective on DMDA 75 76 Input Parameter: 77 + da - initial distributed array 78 . ctype - the vector type, currently either VECSTANDARD or VECCUSP 79 80 Options Database: 81 . -dm_vec_type ctype 82 83 Level: intermediate 84 85 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMDestroy(), DMDA, DMDAInterpolationType, VecType 86 @*/ 87 PetscErrorCode DMSetVecType(DM da,const VecType ctype) 88 { 89 PetscErrorCode ierr; 90 91 PetscFunctionBegin; 92 PetscValidHeaderSpecific(da,DM_CLASSID,1); 93 ierr = PetscFree(da->vectype);CHKERRQ(ierr); 94 ierr = PetscStrallocpy(ctype,&da->vectype);CHKERRQ(ierr); 95 PetscFunctionReturn(0); 96 } 97 98 #undef __FUNCT__ 99 #define __FUNCT__ "DMSetMatType" 100 /*@C 101 DMSetMatType - Sets the type of matrix created with DMCreateMatrix() 102 103 Logically Collective on DM 104 105 Input Parameter: 106 + dm - the DM context 107 . ctype - the matrix type 108 109 Options Database: 110 . -dm_mat_type ctype 111 112 Level: intermediate 113 114 .seealso: DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMCreateMatrix(), DMSetMatrixPreallocateOnly(), MatType 115 @*/ 116 PetscErrorCode DMSetMatType(DM dm,const MatType ctype) 117 { 118 PetscErrorCode ierr; 119 PetscFunctionBegin; 120 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 121 ierr = PetscFree(dm->mattype);CHKERRQ(ierr); 122 ierr = PetscStrallocpy(ctype,&dm->mattype);CHKERRQ(ierr); 123 PetscFunctionReturn(0); 124 } 125 126 #undef __FUNCT__ 127 #define __FUNCT__ "DMSetOptionsPrefix" 128 /*@C 129 DMSetOptionsPrefix - Sets the prefix used for searching for all 130 DMDA options in the database. 131 132 Logically Collective on DMDA 133 134 Input Parameter: 135 + da - the DMDA context 136 - prefix - the prefix to prepend to all option names 137 138 Notes: 139 A hyphen (-) must NOT be given at the beginning of the prefix name. 140 The first character of all runtime options is AUTOMATICALLY the hyphen. 141 142 Level: advanced 143 144 .keywords: DMDA, set, options, prefix, database 145 146 .seealso: DMSetFromOptions() 147 @*/ 148 PetscErrorCode DMSetOptionsPrefix(DM dm,const char prefix[]) 149 { 150 PetscErrorCode ierr; 151 152 PetscFunctionBegin; 153 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 154 ierr = PetscObjectSetOptionsPrefix((PetscObject)dm,prefix);CHKERRQ(ierr); 155 PetscFunctionReturn(0); 156 } 157 158 #undef __FUNCT__ 159 #define __FUNCT__ "DMDestroy" 160 /*@ 161 DMDestroy - Destroys a vector packer or DMDA. 162 163 Collective on DM 164 165 Input Parameter: 166 . dm - the DM object to destroy 167 168 Level: developer 169 170 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 171 172 @*/ 173 PetscErrorCode DMDestroy(DM *dm) 174 { 175 PetscInt i, cnt = 0, f; 176 DMNamedVecLink nlink,nnext; 177 PetscErrorCode ierr; 178 179 PetscFunctionBegin; 180 if (!*dm) PetscFunctionReturn(0); 181 PetscValidHeaderSpecific((*dm),DM_CLASSID,1); 182 183 /* count all the circular references of DM and its contained Vecs */ 184 for (i=0; i<DM_MAX_WORK_VECTORS; i++) { 185 if ((*dm)->localin[i]) {cnt++;} 186 if ((*dm)->globalin[i]) {cnt++;} 187 } 188 for (nlink=(*dm)->namedglobal; nlink; nlink=nlink->next) cnt++; 189 if ((*dm)->x) { 190 PetscObject obj; 191 ierr = PetscObjectQuery((PetscObject)(*dm)->x,"DM",&obj);CHKERRQ(ierr); 192 if (obj == (PetscObject)*dm) cnt++; 193 } 194 195 if (--((PetscObject)(*dm))->refct - cnt > 0) {*dm = 0; PetscFunctionReturn(0);} 196 /* 197 Need this test because the dm references the vectors that 198 reference the dm, so destroying the dm calls destroy on the 199 vectors that cause another destroy on the dm 200 */ 201 if (((PetscObject)(*dm))->refct < 0) PetscFunctionReturn(0); 202 ((PetscObject) (*dm))->refct = 0; 203 for (i=0; i<DM_MAX_WORK_VECTORS; i++) { 204 if ((*dm)->localout[i]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Destroying a DM that has a local vector obtained with DMGetLocalVector()"); 205 ierr = VecDestroy(&(*dm)->localin[i]);CHKERRQ(ierr); 206 } 207 for (nlink=(*dm)->namedglobal; nlink; nlink=nnext) { /* Destroy the named vectors */ 208 nnext = nlink->next; 209 if (nlink->status != DMVEC_STATUS_IN) SETERRQ1(((PetscObject)*dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"DM still has Vec named '%s' checked out",nlink->name); 210 ierr = PetscFree(nlink->name);CHKERRQ(ierr); 211 ierr = VecDestroy(&nlink->X);CHKERRQ(ierr); 212 ierr = PetscFree(nlink);CHKERRQ(ierr); 213 } 214 (*dm)->namedglobal = PETSC_NULL; 215 216 /* Destroy the list of hooks */ 217 { 218 DMCoarsenHookLink link,next; 219 for (link=(*dm)->coarsenhook; link; link=next) { 220 next = link->next; 221 ierr = PetscFree(link);CHKERRQ(ierr); 222 } 223 (*dm)->coarsenhook = PETSC_NULL; 224 } 225 { 226 DMRefineHookLink link,next; 227 for (link=(*dm)->refinehook; link; link=next) { 228 next = link->next; 229 ierr = PetscFree(link);CHKERRQ(ierr); 230 } 231 (*dm)->refinehook = PETSC_NULL; 232 } 233 /* Destroy the work arrays */ 234 { 235 DMWorkLink link,next; 236 if ((*dm)->workout) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Work array still checked out"); 237 for (link=(*dm)->workin; link; link=next) { 238 next = link->next; 239 ierr = PetscFree(link->mem);CHKERRQ(ierr); 240 ierr = PetscFree(link);CHKERRQ(ierr); 241 } 242 (*dm)->workin = PETSC_NULL; 243 } 244 245 if ((*dm)->ctx && (*dm)->ctxdestroy) { 246 ierr = (*(*dm)->ctxdestroy)(&(*dm)->ctx);CHKERRQ(ierr); 247 } 248 ierr = VecDestroy(&(*dm)->x);CHKERRQ(ierr); 249 ierr = MatFDColoringDestroy(&(*dm)->fd);CHKERRQ(ierr); 250 ierr = DMClearGlobalVectors(*dm);CHKERRQ(ierr); 251 ierr = ISLocalToGlobalMappingDestroy(&(*dm)->ltogmap);CHKERRQ(ierr); 252 ierr = ISLocalToGlobalMappingDestroy(&(*dm)->ltogmapb);CHKERRQ(ierr); 253 ierr = PetscFree((*dm)->vectype);CHKERRQ(ierr); 254 ierr = PetscFree((*dm)->mattype);CHKERRQ(ierr); 255 256 ierr = PetscSectionDestroy(&(*dm)->defaultSection);CHKERRQ(ierr); 257 ierr = PetscSectionDestroy(&(*dm)->defaultGlobalSection);CHKERRQ(ierr); 258 ierr = PetscSFDestroy(&(*dm)->sf);CHKERRQ(ierr); 259 ierr = PetscSFDestroy(&(*dm)->defaultSF);CHKERRQ(ierr); 260 261 for(f = 0; f < (*dm)->numFields; ++f) { 262 ierr = PetscObjectDestroy(&(*dm)->fields[f]);CHKERRQ(ierr); 263 } 264 ierr = PetscFree((*dm)->fields);CHKERRQ(ierr); 265 /* if memory was published with AMS then destroy it */ 266 ierr = PetscObjectDepublish(*dm);CHKERRQ(ierr); 267 268 ierr = (*(*dm)->ops->destroy)(*dm);CHKERRQ(ierr); 269 /* We do not destroy (*dm)->data here so that we can reference count backend objects */ 270 ierr = PetscHeaderDestroy(dm);CHKERRQ(ierr); 271 PetscFunctionReturn(0); 272 } 273 274 #undef __FUNCT__ 275 #define __FUNCT__ "DMSetUp" 276 /*@ 277 DMSetUp - sets up the data structures inside a DM object 278 279 Collective on DM 280 281 Input Parameter: 282 . dm - the DM object to setup 283 284 Level: developer 285 286 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 287 288 @*/ 289 PetscErrorCode DMSetUp(DM dm) 290 { 291 PetscErrorCode ierr; 292 293 PetscFunctionBegin; 294 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 295 if (dm->setupcalled) PetscFunctionReturn(0); 296 if (dm->ops->setup) { 297 ierr = (*dm->ops->setup)(dm);CHKERRQ(ierr); 298 } 299 dm->setupcalled = PETSC_TRUE; 300 PetscFunctionReturn(0); 301 } 302 303 #undef __FUNCT__ 304 #define __FUNCT__ "DMSetFromOptions" 305 /*@ 306 DMSetFromOptions - sets parameters in a DM from the options database 307 308 Collective on DM 309 310 Input Parameter: 311 . dm - the DM object to set options for 312 313 Options Database: 314 + -dm_preallocate_only: Only preallocate the matrix for DMCreateMatrix(), but do not fill it with zeros 315 . -dm_vec_type <type> type of vector to create inside DM 316 . -dm_mat_type <type> type of matrix to create inside DM 317 - -dm_coloring_type <global or ghosted> 318 319 Level: developer 320 321 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 322 323 @*/ 324 PetscErrorCode DMSetFromOptions(DM dm) 325 { 326 PetscBool flg1 = PETSC_FALSE,flg2 = PETSC_FALSE,flg3 = PETSC_FALSE,flg4 = PETSC_FALSE,flg; 327 PetscErrorCode ierr; 328 char typeName[256] = MATAIJ; 329 330 PetscFunctionBegin; 331 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 332 ierr = PetscObjectOptionsBegin((PetscObject)dm);CHKERRQ(ierr); 333 ierr = PetscOptionsBool("-dm_view", "Information on DM", "DMView", flg1, &flg1, PETSC_NULL);CHKERRQ(ierr); 334 ierr = PetscOptionsBool("-dm_view_detail", "Exhaustive mesh description", "DMView", flg2, &flg2, PETSC_NULL);CHKERRQ(ierr); 335 ierr = PetscOptionsBool("-dm_view_vtk", "Output mesh in VTK format", "DMView", flg3, &flg3, PETSC_NULL);CHKERRQ(ierr); 336 ierr = PetscOptionsBool("-dm_view_latex", "Output mesh in LaTeX TikZ format", "DMView", flg4, &flg4, PETSC_NULL);CHKERRQ(ierr); 337 ierr = PetscOptionsBool("-dm_preallocate_only","only preallocate matrix, but do not set column indices","DMSetMatrixPreallocateOnly",dm->prealloc_only,&dm->prealloc_only,PETSC_NULL);CHKERRQ(ierr); 338 ierr = PetscOptionsList("-dm_vec_type","Vector type used for created vectors","DMSetVecType",VecList,dm->vectype,typeName,256,&flg);CHKERRQ(ierr); 339 if (flg) { 340 ierr = DMSetVecType(dm,typeName);CHKERRQ(ierr); 341 } 342 ierr = PetscOptionsList("-dm_mat_type","Matrix type used for created matrices","DMSetMatType",MatList,dm->mattype?dm->mattype:typeName,typeName,sizeof typeName,&flg);CHKERRQ(ierr); 343 if (flg) { 344 ierr = DMSetMatType(dm,typeName);CHKERRQ(ierr); 345 } 346 ierr = PetscOptionsEnum("-dm_is_coloring_type","Global or local coloring of Jacobian","ISColoringType",ISColoringTypes,(PetscEnum)dm->coloringtype,(PetscEnum*)&dm->coloringtype,PETSC_NULL);CHKERRQ(ierr); 347 if (dm->ops->setfromoptions) { 348 ierr = (*dm->ops->setfromoptions)(dm);CHKERRQ(ierr); 349 } 350 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 351 ierr = PetscObjectProcessOptionsHandlers((PetscObject) dm);CHKERRQ(ierr); 352 ierr = PetscOptionsEnd();CHKERRQ(ierr); 353 if (flg1) { 354 ierr = DMView(dm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 355 } 356 if (flg2) { 357 PetscViewer viewer; 358 359 ierr = PetscViewerCreate(((PetscObject) dm)->comm, &viewer);CHKERRQ(ierr); 360 ierr = PetscViewerSetType(viewer, PETSCVIEWERASCII);CHKERRQ(ierr); 361 ierr = PetscViewerSetFormat(viewer, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 362 ierr = DMView(dm, viewer);CHKERRQ(ierr); 363 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 364 } 365 if (flg3) { 366 PetscViewer viewer; 367 368 ierr = PetscViewerCreate(((PetscObject) dm)->comm, &viewer);CHKERRQ(ierr); 369 ierr = PetscViewerSetType(viewer, PETSCVIEWERASCII);CHKERRQ(ierr); 370 ierr = PetscViewerSetFormat(viewer, PETSC_VIEWER_ASCII_VTK);CHKERRQ(ierr); 371 ierr = PetscViewerFileSetName(viewer, "mesh.vtk");CHKERRQ(ierr); 372 ierr = DMView(dm, viewer);CHKERRQ(ierr); 373 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 374 } 375 if (flg4) { 376 PetscViewer viewer; 377 378 ierr = PetscViewerCreate(((PetscObject) dm)->comm, &viewer);CHKERRQ(ierr); 379 ierr = PetscViewerSetType(viewer, PETSCVIEWERASCII);CHKERRQ(ierr); 380 ierr = PetscViewerSetFormat(viewer, PETSC_VIEWER_ASCII_LATEX);CHKERRQ(ierr); 381 ierr = PetscViewerFileSetName(viewer, "mesh.tex");CHKERRQ(ierr); 382 ierr = DMView(dm, viewer);CHKERRQ(ierr); 383 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 384 } 385 PetscFunctionReturn(0); 386 } 387 388 #undef __FUNCT__ 389 #define __FUNCT__ "DMView" 390 /*@C 391 DMView - Views a vector packer or DMDA. 392 393 Collective on DM 394 395 Input Parameter: 396 + dm - the DM object to view 397 - v - the viewer 398 399 Level: developer 400 401 .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 402 403 @*/ 404 PetscErrorCode DMView(DM dm,PetscViewer v) 405 { 406 PetscErrorCode ierr; 407 408 PetscFunctionBegin; 409 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 410 if (!v) { 411 ierr = PetscViewerASCIIGetStdout(((PetscObject)dm)->comm,&v);CHKERRQ(ierr); 412 } 413 if (dm->ops->view) { 414 ierr = (*dm->ops->view)(dm,v);CHKERRQ(ierr); 415 } 416 PetscFunctionReturn(0); 417 } 418 419 #undef __FUNCT__ 420 #define __FUNCT__ "DMCreateGlobalVector" 421 /*@ 422 DMCreateGlobalVector - Creates a global vector from a DMDA or DMComposite object 423 424 Collective on DM 425 426 Input Parameter: 427 . dm - the DM object 428 429 Output Parameter: 430 . vec - the global vector 431 432 Level: beginner 433 434 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 435 436 @*/ 437 PetscErrorCode DMCreateGlobalVector(DM dm,Vec *vec) 438 { 439 PetscErrorCode ierr; 440 441 PetscFunctionBegin; 442 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 443 if (dm->defaultSection) { 444 PetscSection gSection; 445 PetscInt localSize; 446 447 ierr = DMGetDefaultGlobalSection(dm, &gSection);CHKERRQ(ierr); 448 ierr = PetscSectionGetConstrainedStorageSize(dm->defaultGlobalSection, &localSize);CHKERRQ(ierr); 449 ierr = VecCreate(((PetscObject) dm)->comm, vec);CHKERRQ(ierr); 450 ierr = VecSetSizes(*vec, localSize, PETSC_DETERMINE);CHKERRQ(ierr); 451 /* ierr = VecSetType(*vec, dm->vectype);CHKERRQ(ierr); */ 452 ierr = VecSetFromOptions(*vec);CHKERRQ(ierr); 453 ierr = PetscObjectCompose((PetscObject) *vec, "DM", (PetscObject) dm);CHKERRQ(ierr); 454 /* ierr = VecSetLocalToGlobalMapping(*vec, dm->ltogmap);CHKERRQ(ierr); */ 455 /* ierr = VecSetLocalToGlobalMappingBlock(*vec, dm->ltogmapb);CHKERRQ(ierr); */ 456 /* ierr = VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM);CHKERRQ(ierr); */ 457 } else { 458 ierr = (*dm->ops->createglobalvector)(dm,vec);CHKERRQ(ierr); 459 } 460 PetscFunctionReturn(0); 461 } 462 463 #undef __FUNCT__ 464 #define __FUNCT__ "DMCreateLocalVector" 465 /*@ 466 DMCreateLocalVector - Creates a local vector from a DMDA or DMComposite object 467 468 Not Collective 469 470 Input Parameter: 471 . dm - the DM object 472 473 Output Parameter: 474 . vec - the local vector 475 476 Level: beginner 477 478 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 479 480 @*/ 481 PetscErrorCode DMCreateLocalVector(DM dm,Vec *vec) 482 { 483 PetscErrorCode ierr; 484 485 PetscFunctionBegin; 486 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 487 if (dm->defaultSection) { 488 PetscInt localSize; 489 490 ierr = PetscSectionGetStorageSize(dm->defaultSection, &localSize);CHKERRQ(ierr); 491 ierr = VecCreate(PETSC_COMM_SELF, vec);CHKERRQ(ierr); 492 ierr = VecSetSizes(*vec, localSize, localSize);CHKERRQ(ierr); 493 ierr = VecSetFromOptions(*vec);CHKERRQ(ierr); 494 ierr = PetscObjectCompose((PetscObject) *vec, "DM", (PetscObject) dm);CHKERRQ(ierr); 495 } else { 496 ierr = (*dm->ops->createlocalvector)(dm,vec);CHKERRQ(ierr); 497 } 498 PetscFunctionReturn(0); 499 } 500 501 #undef __FUNCT__ 502 #define __FUNCT__ "DMGetLocalToGlobalMapping" 503 /*@ 504 DMGetLocalToGlobalMapping - Accesses the local-to-global mapping in a DM. 505 506 Collective on DM 507 508 Input Parameter: 509 . dm - the DM that provides the mapping 510 511 Output Parameter: 512 . ltog - the mapping 513 514 Level: intermediate 515 516 Notes: 517 This mapping can then be used by VecSetLocalToGlobalMapping() or 518 MatSetLocalToGlobalMapping(). 519 520 .seealso: DMCreateLocalVector(), DMGetLocalToGlobalMappingBlock() 521 @*/ 522 PetscErrorCode DMGetLocalToGlobalMapping(DM dm,ISLocalToGlobalMapping *ltog) 523 { 524 PetscErrorCode ierr; 525 526 PetscFunctionBegin; 527 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 528 PetscValidPointer(ltog,2); 529 if (!dm->ltogmap) { 530 PetscSection section, sectionGlobal; 531 532 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 533 if (section) { 534 PetscInt *ltog; 535 PetscInt pStart, pEnd, size, p, l; 536 537 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 538 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 539 ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 540 ierr = PetscMalloc(size * sizeof(PetscInt), <og);CHKERRQ(ierr); /* We want the local+overlap size */ 541 for(p = pStart, l = 0; p < pEnd; ++p) { 542 PetscInt dof, off, c; 543 544 /* Should probably use constrained dofs */ 545 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 546 ierr = PetscSectionGetOffset(sectionGlobal, p, &off);CHKERRQ(ierr); 547 for(c = 0; c < dof; ++c, ++l) { 548 ltog[l] = off+c; 549 } 550 } 551 ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF, size, ltog, PETSC_OWN_POINTER, &dm->ltogmap);CHKERRQ(ierr); 552 ierr = PetscLogObjectParent(dm, dm->ltogmap);CHKERRQ(ierr); 553 } else { 554 if (!dm->ops->createlocaltoglobalmapping) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"DM can not create LocalToGlobalMapping"); 555 ierr = (*dm->ops->createlocaltoglobalmapping)(dm);CHKERRQ(ierr); 556 } 557 } 558 *ltog = dm->ltogmap; 559 PetscFunctionReturn(0); 560 } 561 562 #undef __FUNCT__ 563 #define __FUNCT__ "DMGetLocalToGlobalMappingBlock" 564 /*@ 565 DMGetLocalToGlobalMappingBlock - Accesses the blocked local-to-global mapping in a DM. 566 567 Collective on DM 568 569 Input Parameter: 570 . da - the distributed array that provides the mapping 571 572 Output Parameter: 573 . ltog - the block mapping 574 575 Level: intermediate 576 577 Notes: 578 This mapping can then be used by VecSetLocalToGlobalMappingBlock() or 579 MatSetLocalToGlobalMappingBlock(). 580 581 .seealso: DMCreateLocalVector(), DMGetLocalToGlobalMapping(), DMGetBlockSize(), VecSetBlockSize(), MatSetBlockSize() 582 @*/ 583 PetscErrorCode DMGetLocalToGlobalMappingBlock(DM dm,ISLocalToGlobalMapping *ltog) 584 { 585 PetscErrorCode ierr; 586 587 PetscFunctionBegin; 588 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 589 PetscValidPointer(ltog,2); 590 if (!dm->ltogmapb) { 591 PetscInt bs; 592 ierr = DMGetBlockSize(dm,&bs);CHKERRQ(ierr); 593 if (bs > 1) { 594 if (!dm->ops->createlocaltoglobalmappingblock) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"DM can not create LocalToGlobalMappingBlock"); 595 ierr = (*dm->ops->createlocaltoglobalmappingblock)(dm);CHKERRQ(ierr); 596 } else { 597 ierr = DMGetLocalToGlobalMapping(dm,&dm->ltogmapb);CHKERRQ(ierr); 598 ierr = PetscObjectReference((PetscObject)dm->ltogmapb);CHKERRQ(ierr); 599 } 600 } 601 *ltog = dm->ltogmapb; 602 PetscFunctionReturn(0); 603 } 604 605 #undef __FUNCT__ 606 #define __FUNCT__ "DMGetBlockSize" 607 /*@ 608 DMGetBlockSize - Gets the inherent block size associated with a DM 609 610 Not Collective 611 612 Input Parameter: 613 . dm - the DM with block structure 614 615 Output Parameter: 616 . bs - the block size, 1 implies no exploitable block structure 617 618 Level: intermediate 619 620 .seealso: ISCreateBlock(), VecSetBlockSize(), MatSetBlockSize(), DMGetLocalToGlobalMappingBlock() 621 @*/ 622 PetscErrorCode DMGetBlockSize(DM dm,PetscInt *bs) 623 { 624 PetscFunctionBegin; 625 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 626 PetscValidPointer(bs,2); 627 if (dm->bs < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DM does not have enough information to provide a block size yet"); 628 *bs = dm->bs; 629 PetscFunctionReturn(0); 630 } 631 632 #undef __FUNCT__ 633 #define __FUNCT__ "DMCreateInterpolation" 634 /*@ 635 DMCreateInterpolation - Gets interpolation matrix between two DMDA or DMComposite objects 636 637 Collective on DM 638 639 Input Parameter: 640 + dm1 - the DM object 641 - dm2 - the second, finer DM object 642 643 Output Parameter: 644 + mat - the interpolation 645 - vec - the scaling (optional) 646 647 Level: developer 648 649 Notes: For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by 650 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the interpolation. 651 652 For DMDA objects you can use this interpolation (more precisely the interpolation from the DMDAGetCoordinateDA()) to interpolate the mesh coordinate vectors 653 EXCEPT in the periodic case where it does not make sense since the coordinate vectors are not periodic. 654 655 656 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMRefine(), DMCoarsen() 657 658 @*/ 659 PetscErrorCode DMCreateInterpolation(DM dm1,DM dm2,Mat *mat,Vec *vec) 660 { 661 PetscErrorCode ierr; 662 663 PetscFunctionBegin; 664 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 665 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 666 ierr = (*dm1->ops->createinterpolation)(dm1,dm2,mat,vec);CHKERRQ(ierr); 667 PetscFunctionReturn(0); 668 } 669 670 #undef __FUNCT__ 671 #define __FUNCT__ "DMCreateInjection" 672 /*@ 673 DMCreateInjection - Gets injection matrix between two DMDA or DMComposite objects 674 675 Collective on DM 676 677 Input Parameter: 678 + dm1 - the DM object 679 - dm2 - the second, finer DM object 680 681 Output Parameter: 682 . ctx - the injection 683 684 Level: developer 685 686 Notes: For DMDA objects this only works for "uniform refinement", that is the refined mesh was obtained DMRefine() or the coarse mesh was obtained by 687 DMCoarsen(). The coordinates set into the DMDA are completely ignored in computing the injection. 688 689 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateColoring(), DMCreateMatrix(), DMCreateInterpolation() 690 691 @*/ 692 PetscErrorCode DMCreateInjection(DM dm1,DM dm2,VecScatter *ctx) 693 { 694 PetscErrorCode ierr; 695 696 PetscFunctionBegin; 697 PetscValidHeaderSpecific(dm1,DM_CLASSID,1); 698 PetscValidHeaderSpecific(dm2,DM_CLASSID,2); 699 ierr = (*dm1->ops->getinjection)(dm1,dm2,ctx);CHKERRQ(ierr); 700 PetscFunctionReturn(0); 701 } 702 703 #undef __FUNCT__ 704 #define __FUNCT__ "DMCreateColoring" 705 /*@C 706 DMCreateColoring - Gets coloring for a DMDA or DMComposite 707 708 Collective on DM 709 710 Input Parameter: 711 + dm - the DM object 712 . ctype - IS_COLORING_GHOSTED or IS_COLORING_GLOBAL 713 - matype - either MATAIJ or MATBAIJ 714 715 Output Parameter: 716 . coloring - the coloring 717 718 Level: developer 719 720 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateMatrix() 721 722 @*/ 723 PetscErrorCode DMCreateColoring(DM dm,ISColoringType ctype,const MatType mtype,ISColoring *coloring) 724 { 725 PetscErrorCode ierr; 726 727 PetscFunctionBegin; 728 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 729 if (!dm->ops->getcoloring) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"No coloring for this type of DM yet"); 730 ierr = (*dm->ops->getcoloring)(dm,ctype,mtype,coloring);CHKERRQ(ierr); 731 PetscFunctionReturn(0); 732 } 733 734 #undef __FUNCT__ 735 #define __FUNCT__ "DMCreateMatrix" 736 /*@C 737 DMCreateMatrix - Gets empty Jacobian for a DMDA or DMComposite 738 739 Collective on DM 740 741 Input Parameter: 742 + dm - the DM object 743 - mtype - Supported types are MATSEQAIJ, MATMPIAIJ, MATSEQBAIJ, MATMPIBAIJ, or 744 any type which inherits from one of these (such as MATAIJ) 745 746 Output Parameter: 747 . mat - the empty Jacobian 748 749 Level: beginner 750 751 Notes: This properly preallocates the number of nonzeros in the sparse matrix so you 752 do not need to do it yourself. 753 754 By default it also sets the nonzero structure and puts in the zero entries. To prevent setting 755 the nonzero pattern call DMDASetMatPreallocateOnly() 756 757 For structured grid problems, when you call MatView() on this matrix it is displayed using the global natural ordering, NOT in the ordering used 758 internally by PETSc. 759 760 For structured grid problems, in general it is easiest to use MatSetValuesStencil() or MatSetValuesLocal() to put values into the matrix because MatSetValues() requires 761 the indices for the global numbering for DMDAs which is complicated. 762 763 .seealso DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 764 765 @*/ 766 PetscErrorCode DMCreateMatrix(DM dm,const MatType mtype,Mat *mat) 767 { 768 PetscErrorCode ierr; 769 770 PetscFunctionBegin; 771 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 772 #ifndef PETSC_USE_DYNAMIC_LIBRARIES 773 ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr); 774 #endif 775 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 776 PetscValidPointer(mat,3); 777 if (dm->mattype) { 778 ierr = (*dm->ops->creatematrix)(dm,dm->mattype,mat);CHKERRQ(ierr); 779 } else { 780 ierr = (*dm->ops->creatematrix)(dm,mtype,mat);CHKERRQ(ierr); 781 } 782 PetscFunctionReturn(0); 783 } 784 785 #undef __FUNCT__ 786 #define __FUNCT__ "DMSetMatrixPreallocateOnly" 787 /*@ 788 DMSetMatrixPreallocateOnly - When DMCreateMatrix() is called the matrix will be properly 789 preallocated but the nonzero structure and zero values will not be set. 790 791 Logically Collective on DMDA 792 793 Input Parameter: 794 + dm - the DM 795 - only - PETSC_TRUE if only want preallocation 796 797 Level: developer 798 .seealso DMCreateMatrix() 799 @*/ 800 PetscErrorCode DMSetMatrixPreallocateOnly(DM dm, PetscBool only) 801 { 802 PetscFunctionBegin; 803 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 804 dm->prealloc_only = only; 805 PetscFunctionReturn(0); 806 } 807 808 #undef __FUNCT__ 809 #define __FUNCT__ "DMGetWorkArray" 810 /*@C 811 DMGetWorkArray - Gets a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray() 812 813 Not Collective 814 815 Input Parameters: 816 + dm - the DM object 817 . count - The minium size 818 - dtype - data type (PETSC_REAL, PETSC_SCALAR, PETSC_INT) 819 820 Output Parameter: 821 . array - the work array 822 823 Level: developer 824 825 .seealso DMDestroy(), DMCreate() 826 @*/ 827 PetscErrorCode DMGetWorkArray(DM dm,PetscInt count,PetscDataType dtype,void *mem) 828 { 829 PetscErrorCode ierr; 830 DMWorkLink link; 831 size_t size; 832 833 PetscFunctionBegin; 834 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 835 PetscValidPointer(mem,4); 836 if (dm->workin) { 837 link = dm->workin; 838 dm->workin = dm->workin->next; 839 } else { 840 ierr = PetscNewLog(dm,struct _DMWorkLink,&link);CHKERRQ(ierr); 841 } 842 ierr = PetscDataTypeGetSize(dtype,&size);CHKERRQ(ierr); 843 if (size*count > link->bytes) { 844 ierr = PetscFree(link->mem);CHKERRQ(ierr); 845 ierr = PetscMalloc(size*count,&link->mem);CHKERRQ(ierr); 846 link->bytes = size*count; 847 } 848 link->next = dm->workout; 849 dm->workout = link; 850 *(void**)mem = link->mem; 851 PetscFunctionReturn(0); 852 } 853 854 #undef __FUNCT__ 855 #define __FUNCT__ "DMRestoreWorkArray" 856 /*@C 857 DMRestoreWorkArray - Restores a work array guaranteed to be at least the input size, restore with DMRestoreWorkArray() 858 859 Not Collective 860 861 Input Parameters: 862 + dm - the DM object 863 . count - The minium size 864 - dtype - data type (PETSC_REAL, PETSC_SCALAR, PETSC_INT) 865 866 Output Parameter: 867 . array - the work array 868 869 Level: developer 870 871 .seealso DMDestroy(), DMCreate() 872 @*/ 873 PetscErrorCode DMRestoreWorkArray(DM dm,PetscInt count,PetscDataType dtype,void *mem) 874 { 875 DMWorkLink *p,link; 876 877 PetscFunctionBegin; 878 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 879 PetscValidPointer(mem,4); 880 for (p=&dm->workout; (link=*p); p=&link->next) { 881 if (link->mem == *(void**)mem) { 882 *p = link->next; 883 link->next = dm->workin; 884 dm->workin = link; 885 *(void**)mem = PETSC_NULL; 886 PetscFunctionReturn(0); 887 } 888 } 889 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Array was not checked out"); 890 PetscFunctionReturn(0); 891 } 892 893 #undef __FUNCT__ 894 #define __FUNCT__ "DMSetNullSpaceConstructor" 895 PetscErrorCode DMSetNullSpaceConstructor(DM dm, PetscInt field, PetscErrorCode (*nullsp)(DM dm, PetscInt field, MatNullSpace *nullSpace)) 896 { 897 PetscFunctionBegin; 898 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 899 if (field >= 10) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle %d >= 10 fields", field); 900 dm->nullspaceConstructors[field] = nullsp; 901 PetscFunctionReturn(0); 902 } 903 904 #undef __FUNCT__ 905 #define __FUNCT__ "DMCreateFieldIS" 906 /*@C 907 DMCreateFieldIS - Creates a set of IS objects with the global indices of dofs for each field 908 909 Not collective 910 911 Input Parameter: 912 . dm - the DM object 913 914 Output Parameters: 915 + numFields - The number of fields (or PETSC_NULL if not requested) 916 . fieldNames - The name for each field (or PETSC_NULL if not requested) 917 - fields - The global indices for each field (or PETSC_NULL if not requested) 918 919 Level: intermediate 920 921 Notes: 922 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 923 PetscFree(), every entry of fields should be destroyed with ISDestroy(), and both arrays should be freed with 924 PetscFree(). 925 926 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix() 927 @*/ 928 PetscErrorCode DMCreateFieldIS(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields) 929 { 930 PetscSection section, sectionGlobal; 931 PetscErrorCode ierr; 932 933 PetscFunctionBegin; 934 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 935 if (numFields) { 936 PetscValidPointer(numFields,2); 937 *numFields = 0; 938 } 939 if (fieldNames) { 940 PetscValidPointer(fieldNames,3); 941 *fieldNames = PETSC_NULL; 942 } 943 if (fields) { 944 PetscValidPointer(fields,4); 945 *fields = PETSC_NULL; 946 } 947 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 948 if (section) { 949 PetscInt *fieldSizes, **fieldIndices; 950 PetscInt nF, f, pStart, pEnd, p; 951 952 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 953 ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 954 ierr = PetscMalloc2(nF,PetscInt,&fieldSizes,nF,PetscInt *,&fieldIndices);CHKERRQ(ierr); 955 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 956 for(f = 0; f < nF; ++f) { 957 fieldSizes[f] = 0; 958 } 959 for(p = pStart; p < pEnd; ++p) { 960 PetscInt gdof; 961 962 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 963 if (gdof > 0) { 964 for(f = 0; f < nF; ++f) { 965 PetscInt fdof, fcdof; 966 967 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 968 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 969 fieldSizes[f] += fdof-fcdof; 970 } 971 } 972 } 973 for(f = 0; f < nF; ++f) { 974 ierr = PetscMalloc(fieldSizes[f] * sizeof(PetscInt), &fieldIndices[f]);CHKERRQ(ierr); 975 fieldSizes[f] = 0; 976 } 977 for(p = pStart; p < pEnd; ++p) { 978 PetscInt gdof, goff; 979 980 ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 981 if (gdof > 0) { 982 ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 983 for(f = 0; f < nF; ++f) { 984 PetscInt fdof, fcdof, fc; 985 986 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 987 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 988 for(fc = 0; fc < fdof-fcdof; ++fc, ++fieldSizes[f]) { 989 fieldIndices[f][fieldSizes[f]] = goff++; 990 } 991 } 992 } 993 } 994 if (numFields) {*numFields = nF;} 995 if (fieldNames) { 996 ierr = PetscMalloc(nF * sizeof(char *), fieldNames);CHKERRQ(ierr); 997 for(f = 0; f < nF; ++f) { 998 const char *fieldName; 999 1000 ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr); 1001 ierr = PetscStrallocpy(fieldName, (char **) &(*fieldNames)[f]);CHKERRQ(ierr); 1002 } 1003 } 1004 if (fields) { 1005 ierr = PetscMalloc(nF * sizeof(IS), fields);CHKERRQ(ierr); 1006 for(f = 0; f < nF; ++f) { 1007 ierr = ISCreateGeneral(((PetscObject) dm)->comm, fieldSizes[f], fieldIndices[f], PETSC_OWN_POINTER, &(*fields)[f]);CHKERRQ(ierr); 1008 } 1009 } 1010 ierr = PetscFree2(fieldSizes,fieldIndices);CHKERRQ(ierr); 1011 } else { 1012 if(dm->ops->createfieldis) {ierr = (*dm->ops->createfieldis)(dm, numFields, fieldNames, fields);CHKERRQ(ierr);} 1013 } 1014 PetscFunctionReturn(0); 1015 } 1016 1017 #undef __FUNCT__ 1018 #define __FUNCT__ "DMCreateFieldDecompositionDM" 1019 /*@C 1020 DMCreateFieldDecompositionDM - creates a DM that encapsulates a decomposition of the original DM into fields. 1021 1022 Not Collective 1023 1024 Input Parameters: 1025 + dm - the DM object 1026 - name - the name of the field decomposition 1027 1028 Output Parameter: 1029 . ddm - the field decomposition DM (PETSC_NULL, if no such decomposition is known) 1030 1031 Level: advanced 1032 1033 .seealso DMDestroy(), DMCreate(), DMCreateFieldDecomposition(), DMCreateDomainDecompositionDM() 1034 @*/ 1035 PetscErrorCode DMCreateFieldDecompositionDM(DM dm, const char* name, DM *ddm) 1036 { 1037 PetscErrorCode ierr; 1038 1039 PetscFunctionBegin; 1040 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1041 PetscValidCharPointer(name,2); 1042 PetscValidPointer(ddm,3); 1043 *ddm = PETSC_NULL; 1044 if(dm->ops->createfielddecompositiondm) { 1045 ierr = (*dm->ops->createfielddecompositiondm)(dm,name,ddm); CHKERRQ(ierr); 1046 } 1047 PetscFunctionReturn(0); 1048 } 1049 1050 #undef __FUNCT__ 1051 #define __FUNCT__ "DMCreateFieldDecomposition" 1052 /*@C 1053 DMCreateFieldDecomposition - Returns a list of IS objects defining a decomposition of a problem into subproblems 1054 corresponding to different fields: each IS contains the global indices of the dofs of the 1055 corresponding field. The optional list of DMs define the DM for each subproblem. 1056 Generalizes DMCreateFieldIS(). 1057 1058 Not collective 1059 1060 Input Parameter: 1061 . dm - the DM object 1062 1063 Output Parameters: 1064 + len - The number of subproblems in the field decomposition (or PETSC_NULL if not requested) 1065 . namelist - The name for each field (or PETSC_NULL if not requested) 1066 . islist - The global indices for each field (or PETSC_NULL if not requested) 1067 - dmlist - The DMs for each field subproblem (or PETSC_NULL, if not requested; if PETSC_NULL is returned, no DMs are defined) 1068 1069 Level: intermediate 1070 1071 Notes: 1072 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1073 PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(), 1074 and all of the arrays should be freed with PetscFree(). 1075 1076 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1077 @*/ 1078 PetscErrorCode DMCreateFieldDecomposition(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist) 1079 { 1080 PetscErrorCode ierr; 1081 1082 PetscFunctionBegin; 1083 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1084 if (len) {PetscValidPointer(len,2); *len = 0;} 1085 if (namelist) {PetscValidPointer(namelist,3); *namelist = 0;} 1086 if (islist) {PetscValidPointer(islist,4); *islist = 0;} 1087 if (dmlist) {PetscValidPointer(dmlist,5); *dmlist = 0;} 1088 if (!dm->ops->createfielddecomposition) { 1089 PetscSection section; 1090 PetscInt numFields, f; 1091 1092 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1093 if (section) {ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);} 1094 if (section && numFields && dm->ops->createsubdm) { 1095 *len = numFields; 1096 ierr = PetscMalloc3(numFields,char*,namelist,numFields,IS,islist,numFields,DM,dmlist);CHKERRQ(ierr); 1097 for(f = 0; f < numFields; ++f) { 1098 const char *fieldName; 1099 1100 ierr = DMCreateSubDM(dm, 1, &f, &(*islist)[f], &(*dmlist)[f]);CHKERRQ(ierr); 1101 ierr = PetscSectionGetFieldName(section, f, &fieldName);CHKERRQ(ierr); 1102 ierr = PetscStrallocpy(fieldName, (char **) &(*namelist)[f]);CHKERRQ(ierr); 1103 } 1104 } else { 1105 ierr = DMCreateFieldIS(dm, len, namelist, islist);CHKERRQ(ierr); 1106 /* By default there are no DMs associated with subproblems. */ 1107 if(dmlist) *dmlist = PETSC_NULL; 1108 } 1109 } 1110 else { 1111 ierr = (*dm->ops->createfielddecomposition)(dm,len,namelist,islist,dmlist); CHKERRQ(ierr); 1112 } 1113 PetscFunctionReturn(0); 1114 } 1115 1116 #undef __FUNCT__ 1117 #define __FUNCT__ "DMCreateSubDM" 1118 /*@C 1119 DMCreateSubDM - Returns an IS and DM encapsulating a subproblem defined by the fields passed in. 1120 The fields are defined by DMCreateFieldIS(). 1121 1122 Not collective 1123 1124 Input Parameters: 1125 + dm - the DM object 1126 . numFields - number of fields in this subproblem 1127 - len - The number of subproblems in the decomposition (or PETSC_NULL if not requested) 1128 1129 Output Parameters: 1130 . is - The global indices for the subproblem 1131 - dm - The DM for the subproblem 1132 1133 Level: intermediate 1134 1135 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateFieldIS() 1136 @*/ 1137 PetscErrorCode DMCreateSubDM(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1138 { 1139 PetscErrorCode ierr; 1140 1141 PetscFunctionBegin; 1142 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1143 PetscValidPointer(fields,3); 1144 if (is) {PetscValidPointer(is,4);} 1145 if (subdm) {PetscValidPointer(subdm,5);} 1146 if (dm->ops->createsubdm) { 1147 ierr = (*dm->ops->createsubdm)(dm, numFields, fields, is, subdm); CHKERRQ(ierr); 1148 } else SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "This type has no DMCreateSubDM implementation defined"); 1149 PetscFunctionReturn(0); 1150 } 1151 1152 #undef __FUNCT__ 1153 #define __FUNCT__ "DMCreateDomainDecompositionDM" 1154 /*@C 1155 DMCreateDomainDecompositionDM - creates a DM that encapsulates a decomposition of the original DM into subdomains. 1156 1157 Not Collective 1158 1159 Input Parameters: 1160 + dm - the DM object 1161 - name - the name of the subdomain decomposition 1162 1163 Output Parameter: 1164 . ddm - the subdomain decomposition DM (PETSC_NULL, if no such decomposition is known) 1165 1166 Level: advanced 1167 1168 .seealso DMDestroy(), DMCreate(), DMCreateFieldDecomposition(), DMCreateDomainDecompositionDM() 1169 @*/ 1170 PetscErrorCode DMCreateDomainDecompositionDM(DM dm, const char* name, DM *ddm) 1171 { 1172 PetscErrorCode ierr; 1173 1174 PetscFunctionBegin; 1175 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1176 PetscValidCharPointer(name,2); 1177 PetscValidPointer(ddm,3); 1178 *ddm = PETSC_NULL; 1179 if(dm->ops->createdomaindecompositiondm) { 1180 ierr = (*dm->ops->createdomaindecompositiondm)(dm,name,ddm); CHKERRQ(ierr); 1181 } 1182 PetscFunctionReturn(0); 1183 } 1184 1185 #undef __FUNCT__ 1186 #define __FUNCT__ "DMCreateDomainDecomposition" 1187 /*@C 1188 DMCreateDomainDecomposition - Returns lists of IS objects defining a decomposition of a problem into subproblems 1189 corresponding to restrictions to pairs nested subdomains: each IS contains the global 1190 indices of the dofs of the corresponding subdomains. The inner subdomains conceptually 1191 define a nonoverlapping covering, while outer subdomains can overlap. 1192 The optional list of DMs define the DM for each subproblem. 1193 1194 Not collective 1195 1196 Input Parameter: 1197 . dm - the DM object 1198 1199 Output Parameters: 1200 + len - The number of subproblems in the domain decomposition (or PETSC_NULL if not requested) 1201 . namelist - The name for each subdomain (or PETSC_NULL if not requested) 1202 . innerislist - The global indices for each inner subdomain (or PETSC_NULL, if not requested) 1203 . outerislist - The global indices for each outer subdomain (or PETSC_NULL, if not requested) 1204 - dmlist - The DMs for each subdomain subproblem (or PETSC_NULL, if not requested; if PETSC_NULL is returned, no DMs are defined) 1205 1206 Level: intermediate 1207 1208 Notes: 1209 The user is responsible for freeing all requested arrays. In particular, every entry of names should be freed with 1210 PetscFree(), every entry of is should be destroyed with ISDestroy(), every entry of dm should be destroyed with DMDestroy(), 1211 and all of the arrays should be freed with PetscFree(). 1212 1213 .seealso DMDestroy(), DMView(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMCreateDomainDecompositionDM(), DMCreateFieldDecomposition() 1214 @*/ 1215 PetscErrorCode DMCreateDomainDecomposition(DM dm, PetscInt *len, char ***namelist, IS **innerislist, IS **outerislist, DM **dmlist) 1216 { 1217 PetscErrorCode ierr; 1218 1219 PetscFunctionBegin; 1220 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1221 if (len) {PetscValidPointer(len,2); *len = PETSC_NULL;} 1222 if (namelist) {PetscValidPointer(namelist,3); *namelist = PETSC_NULL;} 1223 if (innerislist) {PetscValidPointer(innerislist,4); *innerislist = PETSC_NULL;} 1224 if (outerislist) {PetscValidPointer(outerislist,5); *outerislist = PETSC_NULL;} 1225 if (dmlist) {PetscValidPointer(dmlist,6); *dmlist = PETSC_NULL;} 1226 if(dm->ops->createdomaindecomposition) { 1227 ierr = (*dm->ops->createdomaindecomposition)(dm,len,namelist,innerislist,outerislist,dmlist); CHKERRQ(ierr); 1228 } 1229 PetscFunctionReturn(0); 1230 } 1231 1232 #undef __FUNCT__ 1233 #define __FUNCT__ "DMRefine" 1234 /*@ 1235 DMRefine - Refines a DM object 1236 1237 Collective on DM 1238 1239 Input Parameter: 1240 + dm - the DM object 1241 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 1242 1243 Output Parameter: 1244 . dmf - the refined DM, or PETSC_NULL 1245 1246 Note: If no refinement was done, the return value is PETSC_NULL 1247 1248 Level: developer 1249 1250 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1251 @*/ 1252 PetscErrorCode DMRefine(DM dm,MPI_Comm comm,DM *dmf) 1253 { 1254 PetscErrorCode ierr; 1255 DMRefineHookLink link; 1256 1257 PetscFunctionBegin; 1258 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1259 ierr = (*dm->ops->refine)(dm,comm,dmf);CHKERRQ(ierr); 1260 if (*dmf) { 1261 (*dmf)->ops->creatematrix = dm->ops->creatematrix; 1262 (*dmf)->ops->initialguess = dm->ops->initialguess; 1263 (*dmf)->ops->function = dm->ops->function; 1264 (*dmf)->ops->functionj = dm->ops->functionj; 1265 if (dm->ops->jacobian != DMComputeJacobianDefault) { 1266 (*dmf)->ops->jacobian = dm->ops->jacobian; 1267 } 1268 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmf);CHKERRQ(ierr); 1269 (*dmf)->ctx = dm->ctx; 1270 (*dmf)->leveldown = dm->leveldown; 1271 (*dmf)->levelup = dm->levelup + 1; 1272 ierr = DMSetMatType(*dmf,dm->mattype);CHKERRQ(ierr); 1273 for (link=dm->refinehook; link; link=link->next) { 1274 if (link->refinehook) {ierr = (*link->refinehook)(dm,*dmf,link->ctx);CHKERRQ(ierr);} 1275 } 1276 } 1277 PetscFunctionReturn(0); 1278 } 1279 1280 #undef __FUNCT__ 1281 #define __FUNCT__ "DMRefineHookAdd" 1282 /*@ 1283 DMRefineHookAdd - adds a callback to be run when interpolating a nonlinear problem to a finer grid 1284 1285 Logically Collective 1286 1287 Input Arguments: 1288 + coarse - nonlinear solver context on which to run a hook when restricting to a coarser level 1289 . refinehook - function to run when setting up a coarser level 1290 . interphook - function to run to update data on finer levels (once per SNESSolve()) 1291 - ctx - [optional] user-defined context for provide data for the hooks (may be PETSC_NULL) 1292 1293 Calling sequence of refinehook: 1294 $ refinehook(DM coarse,DM fine,void *ctx); 1295 1296 + coarse - coarse level DM 1297 . fine - fine level DM to interpolate problem to 1298 - ctx - optional user-defined function context 1299 1300 Calling sequence for interphook: 1301 $ interphook(DM coarse,Mat interp,DM fine,void *ctx) 1302 1303 + coarse - coarse level DM 1304 . interp - matrix interpolating a coarse-level solution to the finer grid 1305 . fine - fine level DM to update 1306 - ctx - optional user-defined function context 1307 1308 Level: advanced 1309 1310 Notes: 1311 This function is only needed if auxiliary data needs to be passed to fine grids while grid sequencing 1312 1313 If this function is called multiple times, the hooks will be run in the order they are added. 1314 1315 .seealso: DMCoarsenHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 1316 @*/ 1317 PetscErrorCode DMRefineHookAdd(DM coarse,PetscErrorCode (*refinehook)(DM,DM,void*),PetscErrorCode (*interphook)(DM,Mat,DM,void*),void *ctx) 1318 { 1319 PetscErrorCode ierr; 1320 DMRefineHookLink link,*p; 1321 1322 PetscFunctionBegin; 1323 PetscValidHeaderSpecific(coarse,DM_CLASSID,1); 1324 for (p=&coarse->refinehook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 1325 ierr = PetscMalloc(sizeof(struct _DMRefineHookLink),&link);CHKERRQ(ierr); 1326 link->refinehook = refinehook; 1327 link->interphook = interphook; 1328 link->ctx = ctx; 1329 link->next = PETSC_NULL; 1330 *p = link; 1331 PetscFunctionReturn(0); 1332 } 1333 1334 #undef __FUNCT__ 1335 #define __FUNCT__ "DMInterpolate" 1336 /*@ 1337 DMInterpolate - interpolates user-defined problem data to a finer DM by running hooks registered by DMRefineHookAdd() 1338 1339 Collective if any hooks are 1340 1341 Input Arguments: 1342 + coarse - coarser DM to use as a base 1343 . restrct - interpolation matrix, apply using MatInterpolate() 1344 - fine - finer DM to update 1345 1346 Level: developer 1347 1348 .seealso: DMRefineHookAdd(), MatInterpolate() 1349 @*/ 1350 PetscErrorCode DMInterpolate(DM coarse,Mat interp,DM fine) 1351 { 1352 PetscErrorCode ierr; 1353 DMRefineHookLink link; 1354 1355 PetscFunctionBegin; 1356 for (link=fine->refinehook; link; link=link->next) { 1357 if (link->interphook) {ierr = (*link->interphook)(coarse,interp,fine,link->ctx);CHKERRQ(ierr);} 1358 } 1359 PetscFunctionReturn(0); 1360 } 1361 1362 #undef __FUNCT__ 1363 #define __FUNCT__ "DMGetRefineLevel" 1364 /*@ 1365 DMGetRefineLevel - Get's the number of refinements that have generated this DM. 1366 1367 Not Collective 1368 1369 Input Parameter: 1370 . dm - the DM object 1371 1372 Output Parameter: 1373 . level - number of refinements 1374 1375 Level: developer 1376 1377 .seealso DMCoarsen(), DMGetCoarsenLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1378 1379 @*/ 1380 PetscErrorCode DMGetRefineLevel(DM dm,PetscInt *level) 1381 { 1382 PetscFunctionBegin; 1383 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1384 *level = dm->levelup; 1385 PetscFunctionReturn(0); 1386 } 1387 1388 #undef __FUNCT__ 1389 #define __FUNCT__ "DMGlobalToLocalBegin" 1390 /*@ 1391 DMGlobalToLocalBegin - Begins updating local vectors from global vector 1392 1393 Neighbor-wise Collective on DM 1394 1395 Input Parameters: 1396 + dm - the DM object 1397 . g - the global vector 1398 . mode - INSERT_VALUES or ADD_VALUES 1399 - l - the local vector 1400 1401 1402 Level: beginner 1403 1404 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 1405 1406 @*/ 1407 PetscErrorCode DMGlobalToLocalBegin(DM dm,Vec g,InsertMode mode,Vec l) 1408 { 1409 PetscSF sf; 1410 PetscErrorCode ierr; 1411 1412 PetscFunctionBegin; 1413 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1414 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 1415 if (sf) { 1416 PetscScalar *lArray, *gArray; 1417 1418 if (mode == ADD_VALUES) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 1419 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 1420 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 1421 ierr = PetscSFBcastBegin(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr); 1422 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 1423 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 1424 } else { 1425 ierr = (*dm->ops->globaltolocalbegin)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 1426 } 1427 PetscFunctionReturn(0); 1428 } 1429 1430 #undef __FUNCT__ 1431 #define __FUNCT__ "DMGlobalToLocalEnd" 1432 /*@ 1433 DMGlobalToLocalEnd - Ends updating local vectors from global vector 1434 1435 Neighbor-wise Collective on DM 1436 1437 Input Parameters: 1438 + dm - the DM object 1439 . g - the global vector 1440 . mode - INSERT_VALUES or ADD_VALUES 1441 - l - the local vector 1442 1443 1444 Level: beginner 1445 1446 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMLocalToGlobalBegin() 1447 1448 @*/ 1449 PetscErrorCode DMGlobalToLocalEnd(DM dm,Vec g,InsertMode mode,Vec l) 1450 { 1451 PetscSF sf; 1452 PetscErrorCode ierr; 1453 PetscScalar *lArray, *gArray; 1454 1455 PetscFunctionBegin; 1456 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1457 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 1458 if (sf) { 1459 if (mode == ADD_VALUES) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 1460 1461 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 1462 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 1463 ierr = PetscSFBcastEnd(sf, MPIU_SCALAR, gArray, lArray);CHKERRQ(ierr); 1464 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 1465 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 1466 } else { 1467 ierr = (*dm->ops->globaltolocalend)(dm,g,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),l);CHKERRQ(ierr); 1468 } 1469 PetscFunctionReturn(0); 1470 } 1471 1472 #undef __FUNCT__ 1473 #define __FUNCT__ "DMLocalToGlobalBegin" 1474 /*@ 1475 DMLocalToGlobalBegin - updates global vectors from local vectors 1476 1477 Neighbor-wise Collective on DM 1478 1479 Input Parameters: 1480 + dm - the DM object 1481 . l - the local vector 1482 . mode - if INSERT_VALUES then no parallel communication is used, if ADD_VALUES then all ghost points from the same base point accumulate into that 1483 base point. 1484 - - the global vector 1485 1486 Notes: In the ADD_VALUES case you normally would zero the receiving vector before beginning this operation. If you would like to simply add the non-ghosted values in the local 1487 array into the global array you need to either (1) zero the ghosted locations and use ADD_VALUES or (2) use INSERT_VALUES into a work global array and then add the work 1488 global array to the final global array with VecAXPY(). 1489 1490 Level: beginner 1491 1492 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalBegin() 1493 1494 @*/ 1495 PetscErrorCode DMLocalToGlobalBegin(DM dm,Vec l,InsertMode mode,Vec g) 1496 { 1497 PetscSF sf; 1498 PetscErrorCode ierr; 1499 1500 PetscFunctionBegin; 1501 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1502 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 1503 if (sf) { 1504 MPI_Op op; 1505 PetscScalar *lArray, *gArray; 1506 1507 switch(mode) { 1508 case INSERT_VALUES: 1509 case INSERT_ALL_VALUES: 1510 #if defined(PETSC_HAVE_MPI_REPLACE) 1511 op = MPI_REPLACE; break; 1512 #else 1513 SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"No support for INSERT_VALUES without an MPI-2 implementation"); 1514 #endif 1515 case ADD_VALUES: 1516 case ADD_ALL_VALUES: 1517 op = MPI_SUM; break; 1518 default: 1519 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 1520 } 1521 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 1522 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 1523 ierr = PetscSFReduceBegin(sf, MPIU_SCALAR, lArray, gArray, op);CHKERRQ(ierr); 1524 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 1525 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 1526 } else { 1527 ierr = (*dm->ops->localtoglobalbegin)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 1528 } 1529 PetscFunctionReturn(0); 1530 } 1531 1532 #undef __FUNCT__ 1533 #define __FUNCT__ "DMLocalToGlobalEnd" 1534 /*@ 1535 DMLocalToGlobalEnd - updates global vectors from local vectors 1536 1537 Neighbor-wise Collective on DM 1538 1539 Input Parameters: 1540 + dm - the DM object 1541 . l - the local vector 1542 . mode - INSERT_VALUES or ADD_VALUES 1543 - g - the global vector 1544 1545 1546 Level: beginner 1547 1548 .seealso DMCoarsen(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMGlobalToLocalEnd(), DMGlobalToLocalEnd() 1549 1550 @*/ 1551 PetscErrorCode DMLocalToGlobalEnd(DM dm,Vec l,InsertMode mode,Vec g) 1552 { 1553 PetscSF sf; 1554 PetscErrorCode ierr; 1555 1556 PetscFunctionBegin; 1557 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1558 ierr = DMGetDefaultSF(dm, &sf);CHKERRQ(ierr); 1559 if (sf) { 1560 MPI_Op op; 1561 PetscScalar *lArray, *gArray; 1562 1563 switch(mode) { 1564 case INSERT_VALUES: 1565 case INSERT_ALL_VALUES: 1566 #if defined(PETSC_HAVE_MPI_REPLACE) 1567 op = MPI_REPLACE; break; 1568 #else 1569 SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"No support for INSERT_VALUES without an MPI-2 implementation"); 1570 #endif 1571 case ADD_VALUES: 1572 case ADD_ALL_VALUES: 1573 op = MPI_SUM; break; 1574 default: 1575 SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insertion mode %D", mode); 1576 } 1577 ierr = VecGetArray(l, &lArray);CHKERRQ(ierr); 1578 ierr = VecGetArray(g, &gArray);CHKERRQ(ierr); 1579 ierr = PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, op);CHKERRQ(ierr); 1580 ierr = VecRestoreArray(l, &lArray);CHKERRQ(ierr); 1581 ierr = VecRestoreArray(g, &gArray);CHKERRQ(ierr); 1582 } else { 1583 ierr = (*dm->ops->localtoglobalend)(dm,l,mode == INSERT_ALL_VALUES ? INSERT_VALUES : (mode == ADD_ALL_VALUES ? ADD_VALUES : mode),g);CHKERRQ(ierr); 1584 } 1585 PetscFunctionReturn(0); 1586 } 1587 1588 #undef __FUNCT__ 1589 #define __FUNCT__ "DMComputeJacobianDefault" 1590 /*@ 1591 DMComputeJacobianDefault - computes the Jacobian using the DMComputeFunction() if Jacobian computer is not provided 1592 1593 Collective on DM 1594 1595 Input Parameter: 1596 + dm - the DM object 1597 . x - location to compute Jacobian at; may be ignored for linear problems 1598 . A - matrix that defines the operator for the linear solve 1599 - B - the matrix used to construct the preconditioner 1600 1601 Level: developer 1602 1603 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), DMSetInitialGuess(), 1604 DMSetFunction() 1605 1606 @*/ 1607 PetscErrorCode DMComputeJacobianDefault(DM dm,Vec x,Mat A,Mat B,MatStructure *stflag) 1608 { 1609 PetscErrorCode ierr; 1610 1611 PetscFunctionBegin; 1612 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1613 *stflag = SAME_NONZERO_PATTERN; 1614 ierr = MatFDColoringApply(B,dm->fd,x,stflag,dm);CHKERRQ(ierr); 1615 if (A != B) { 1616 ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1617 ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1618 } 1619 PetscFunctionReturn(0); 1620 } 1621 1622 #undef __FUNCT__ 1623 #define __FUNCT__ "DMCoarsen" 1624 /*@ 1625 DMCoarsen - Coarsens a DM object 1626 1627 Collective on DM 1628 1629 Input Parameter: 1630 + dm - the DM object 1631 - comm - the communicator to contain the new DM object (or MPI_COMM_NULL) 1632 1633 Output Parameter: 1634 . dmc - the coarsened DM 1635 1636 Level: developer 1637 1638 .seealso DMRefine(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1639 1640 @*/ 1641 PetscErrorCode DMCoarsen(DM dm, MPI_Comm comm, DM *dmc) 1642 { 1643 PetscErrorCode ierr; 1644 DMCoarsenHookLink link; 1645 1646 PetscFunctionBegin; 1647 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1648 ierr = (*dm->ops->coarsen)(dm, comm, dmc);CHKERRQ(ierr); 1649 (*dmc)->ops->creatematrix = dm->ops->creatematrix; 1650 (*dmc)->ops->initialguess = dm->ops->initialguess; 1651 (*dmc)->ops->function = dm->ops->function; 1652 (*dmc)->ops->functionj = dm->ops->functionj; 1653 if (dm->ops->jacobian != DMComputeJacobianDefault) { 1654 (*dmc)->ops->jacobian = dm->ops->jacobian; 1655 } 1656 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)dm,(PetscObject)*dmc);CHKERRQ(ierr); 1657 (*dmc)->ctx = dm->ctx; 1658 (*dmc)->levelup = dm->levelup; 1659 (*dmc)->leveldown = dm->leveldown + 1; 1660 ierr = DMSetMatType(*dmc,dm->mattype);CHKERRQ(ierr); 1661 for (link=dm->coarsenhook; link; link=link->next) { 1662 if (link->coarsenhook) {ierr = (*link->coarsenhook)(dm,*dmc,link->ctx);CHKERRQ(ierr);} 1663 } 1664 PetscFunctionReturn(0); 1665 } 1666 1667 #undef __FUNCT__ 1668 #define __FUNCT__ "DMCoarsenHookAdd" 1669 /*@ 1670 DMCoarsenHookAdd - adds a callback to be run when restricting a nonlinear problem to the coarse grid 1671 1672 Logically Collective 1673 1674 Input Arguments: 1675 + fine - nonlinear solver context on which to run a hook when restricting to a coarser level 1676 . coarsenhook - function to run when setting up a coarser level 1677 . restricthook - function to run to update data on coarser levels (once per SNESSolve()) 1678 - ctx - [optional] user-defined context for provide data for the hooks (may be PETSC_NULL) 1679 1680 Calling sequence of coarsenhook: 1681 $ coarsenhook(DM fine,DM coarse,void *ctx); 1682 1683 + fine - fine level DM 1684 . coarse - coarse level DM to restrict problem to 1685 - ctx - optional user-defined function context 1686 1687 Calling sequence for restricthook: 1688 $ restricthook(DM fine,Mat mrestrict,Vec rscale,Mat inject,DM coarse,void *ctx) 1689 1690 + fine - fine level DM 1691 . mrestrict - matrix restricting a fine-level solution to the coarse grid 1692 . rscale - scaling vector for restriction 1693 . inject - matrix restricting by injection 1694 . coarse - coarse level DM to update 1695 - ctx - optional user-defined function context 1696 1697 Level: advanced 1698 1699 Notes: 1700 This function is only needed if auxiliary data needs to be set up on coarse grids. 1701 1702 If this function is called multiple times, the hooks will be run in the order they are added. 1703 1704 In order to compose with nonlinear preconditioning without duplicating storage, the hook should be implemented to 1705 extract the finest level information from its context (instead of from the SNES). 1706 1707 .seealso: DMRefineHookAdd(), SNESFASGetInterpolation(), SNESFASGetInjection(), PetscObjectCompose(), PetscContainerCreate() 1708 @*/ 1709 PetscErrorCode DMCoarsenHookAdd(DM fine,PetscErrorCode (*coarsenhook)(DM,DM,void*),PetscErrorCode (*restricthook)(DM,Mat,Vec,Mat,DM,void*),void *ctx) 1710 { 1711 PetscErrorCode ierr; 1712 DMCoarsenHookLink link,*p; 1713 1714 PetscFunctionBegin; 1715 PetscValidHeaderSpecific(fine,DM_CLASSID,1); 1716 for (p=&fine->coarsenhook; *p; p=&(*p)->next) {} /* Scan to the end of the current list of hooks */ 1717 ierr = PetscMalloc(sizeof(struct _DMCoarsenHookLink),&link);CHKERRQ(ierr); 1718 link->coarsenhook = coarsenhook; 1719 link->restricthook = restricthook; 1720 link->ctx = ctx; 1721 link->next = PETSC_NULL; 1722 *p = link; 1723 PetscFunctionReturn(0); 1724 } 1725 1726 #undef __FUNCT__ 1727 #define __FUNCT__ "DMRestrict" 1728 /*@ 1729 DMRestrict - restricts user-defined problem data to a coarser DM by running hooks registered by DMCoarsenHookAdd() 1730 1731 Collective if any hooks are 1732 1733 Input Arguments: 1734 + fine - finer DM to use as a base 1735 . restrct - restriction matrix, apply using MatRestrict() 1736 . inject - injection matrix, also use MatRestrict() 1737 - coarse - coarer DM to update 1738 1739 Level: developer 1740 1741 .seealso: DMCoarsenHookAdd(), MatRestrict() 1742 @*/ 1743 PetscErrorCode DMRestrict(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse) 1744 { 1745 PetscErrorCode ierr; 1746 DMCoarsenHookLink link; 1747 1748 PetscFunctionBegin; 1749 for (link=fine->coarsenhook; link; link=link->next) { 1750 if (link->restricthook) {ierr = (*link->restricthook)(fine,restrct,rscale,inject,coarse,link->ctx);CHKERRQ(ierr);} 1751 } 1752 PetscFunctionReturn(0); 1753 } 1754 1755 #undef __FUNCT__ 1756 #define __FUNCT__ "DMGetCoarsenLevel" 1757 /*@ 1758 DMGetCoarsenLevel - Get's the number of coarsenings that have generated this DM. 1759 1760 Not Collective 1761 1762 Input Parameter: 1763 . dm - the DM object 1764 1765 Output Parameter: 1766 . level - number of coarsenings 1767 1768 Level: developer 1769 1770 .seealso DMCoarsen(), DMGetRefineLevel(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1771 1772 @*/ 1773 PetscErrorCode DMGetCoarsenLevel(DM dm,PetscInt *level) 1774 { 1775 PetscFunctionBegin; 1776 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1777 *level = dm->leveldown; 1778 PetscFunctionReturn(0); 1779 } 1780 1781 1782 1783 #undef __FUNCT__ 1784 #define __FUNCT__ "DMRefineHierarchy" 1785 /*@C 1786 DMRefineHierarchy - Refines a DM object, all levels at once 1787 1788 Collective on DM 1789 1790 Input Parameter: 1791 + dm - the DM object 1792 - nlevels - the number of levels of refinement 1793 1794 Output Parameter: 1795 . dmf - the refined DM hierarchy 1796 1797 Level: developer 1798 1799 .seealso DMCoarsenHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1800 1801 @*/ 1802 PetscErrorCode DMRefineHierarchy(DM dm,PetscInt nlevels,DM dmf[]) 1803 { 1804 PetscErrorCode ierr; 1805 1806 PetscFunctionBegin; 1807 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1808 if (nlevels < 0) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 1809 if (nlevels == 0) PetscFunctionReturn(0); 1810 if (dm->ops->refinehierarchy) { 1811 ierr = (*dm->ops->refinehierarchy)(dm,nlevels,dmf);CHKERRQ(ierr); 1812 } else if (dm->ops->refine) { 1813 PetscInt i; 1814 1815 ierr = DMRefine(dm,((PetscObject)dm)->comm,&dmf[0]);CHKERRQ(ierr); 1816 for (i=1; i<nlevels; i++) { 1817 ierr = DMRefine(dmf[i-1],((PetscObject)dm)->comm,&dmf[i]);CHKERRQ(ierr); 1818 } 1819 } else { 1820 SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"No RefineHierarchy for this DM yet"); 1821 } 1822 PetscFunctionReturn(0); 1823 } 1824 1825 #undef __FUNCT__ 1826 #define __FUNCT__ "DMCoarsenHierarchy" 1827 /*@C 1828 DMCoarsenHierarchy - Coarsens a DM object, all levels at once 1829 1830 Collective on DM 1831 1832 Input Parameter: 1833 + dm - the DM object 1834 - nlevels - the number of levels of coarsening 1835 1836 Output Parameter: 1837 . dmc - the coarsened DM hierarchy 1838 1839 Level: developer 1840 1841 .seealso DMRefineHierarchy(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateInterpolation() 1842 1843 @*/ 1844 PetscErrorCode DMCoarsenHierarchy(DM dm, PetscInt nlevels, DM dmc[]) 1845 { 1846 PetscErrorCode ierr; 1847 1848 PetscFunctionBegin; 1849 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1850 if (nlevels < 0) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_OUTOFRANGE,"nlevels cannot be negative"); 1851 if (nlevels == 0) PetscFunctionReturn(0); 1852 PetscValidPointer(dmc,3); 1853 if (dm->ops->coarsenhierarchy) { 1854 ierr = (*dm->ops->coarsenhierarchy)(dm, nlevels, dmc);CHKERRQ(ierr); 1855 } else if (dm->ops->coarsen) { 1856 PetscInt i; 1857 1858 ierr = DMCoarsen(dm,((PetscObject)dm)->comm,&dmc[0]);CHKERRQ(ierr); 1859 for (i=1; i<nlevels; i++) { 1860 ierr = DMCoarsen(dmc[i-1],((PetscObject)dm)->comm,&dmc[i]);CHKERRQ(ierr); 1861 } 1862 } else { 1863 SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"No CoarsenHierarchy for this DM yet"); 1864 } 1865 PetscFunctionReturn(0); 1866 } 1867 1868 #undef __FUNCT__ 1869 #define __FUNCT__ "DMCreateAggregates" 1870 /*@ 1871 DMCreateAggregates - Gets the aggregates that map between 1872 grids associated with two DMs. 1873 1874 Collective on DM 1875 1876 Input Parameters: 1877 + dmc - the coarse grid DM 1878 - dmf - the fine grid DM 1879 1880 Output Parameters: 1881 . rest - the restriction matrix (transpose of the projection matrix) 1882 1883 Level: intermediate 1884 1885 .keywords: interpolation, restriction, multigrid 1886 1887 .seealso: DMRefine(), DMCreateInjection(), DMCreateInterpolation() 1888 @*/ 1889 PetscErrorCode DMCreateAggregates(DM dmc, DM dmf, Mat *rest) 1890 { 1891 PetscErrorCode ierr; 1892 1893 PetscFunctionBegin; 1894 PetscValidHeaderSpecific(dmc,DM_CLASSID,1); 1895 PetscValidHeaderSpecific(dmf,DM_CLASSID,2); 1896 ierr = (*dmc->ops->getaggregates)(dmc, dmf, rest);CHKERRQ(ierr); 1897 PetscFunctionReturn(0); 1898 } 1899 1900 #undef __FUNCT__ 1901 #define __FUNCT__ "DMSetApplicationContextDestroy" 1902 /*@C 1903 DMSetApplicationContextDestroy - Sets a user function that will be called to destroy the application context when the DM is destroyed 1904 1905 Not Collective 1906 1907 Input Parameters: 1908 + dm - the DM object 1909 - destroy - the destroy function 1910 1911 Level: intermediate 1912 1913 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 1914 1915 @*/ 1916 PetscErrorCode DMSetApplicationContextDestroy(DM dm,PetscErrorCode (*destroy)(void**)) 1917 { 1918 PetscFunctionBegin; 1919 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1920 dm->ctxdestroy = destroy; 1921 PetscFunctionReturn(0); 1922 } 1923 1924 #undef __FUNCT__ 1925 #define __FUNCT__ "DMSetApplicationContext" 1926 /*@ 1927 DMSetApplicationContext - Set a user context into a DM object 1928 1929 Not Collective 1930 1931 Input Parameters: 1932 + dm - the DM object 1933 - ctx - the user context 1934 1935 Level: intermediate 1936 1937 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 1938 1939 @*/ 1940 PetscErrorCode DMSetApplicationContext(DM dm,void *ctx) 1941 { 1942 PetscFunctionBegin; 1943 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1944 dm->ctx = ctx; 1945 PetscFunctionReturn(0); 1946 } 1947 1948 #undef __FUNCT__ 1949 #define __FUNCT__ "DMGetApplicationContext" 1950 /*@ 1951 DMGetApplicationContext - Gets a user context from a DM object 1952 1953 Not Collective 1954 1955 Input Parameter: 1956 . dm - the DM object 1957 1958 Output Parameter: 1959 . ctx - the user context 1960 1961 Level: intermediate 1962 1963 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext() 1964 1965 @*/ 1966 PetscErrorCode DMGetApplicationContext(DM dm,void *ctx) 1967 { 1968 PetscFunctionBegin; 1969 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1970 *(void**)ctx = dm->ctx; 1971 PetscFunctionReturn(0); 1972 } 1973 1974 #undef __FUNCT__ 1975 #define __FUNCT__ "DMSetInitialGuess" 1976 /*@C 1977 DMSetInitialGuess - sets a function to compute an initial guess vector entries for the solvers 1978 1979 Logically Collective on DM 1980 1981 Input Parameter: 1982 + dm - the DM object to destroy 1983 - f - the function to compute the initial guess 1984 1985 Level: intermediate 1986 1987 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), DMSetFunction(), DMSetJacobian() 1988 1989 @*/ 1990 PetscErrorCode DMSetInitialGuess(DM dm,PetscErrorCode (*f)(DM,Vec)) 1991 { 1992 PetscFunctionBegin; 1993 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 1994 dm->ops->initialguess = f; 1995 PetscFunctionReturn(0); 1996 } 1997 1998 #undef __FUNCT__ 1999 #define __FUNCT__ "DMSetFunction" 2000 /*@C 2001 DMSetFunction - sets a function to compute the right hand side vector entries for the KSP solver or nonlinear function for SNES 2002 2003 Logically Collective on DM 2004 2005 Input Parameter: 2006 + dm - the DM object 2007 - f - the function to compute (use PETSC_NULL to cancel a previous function that was set) 2008 2009 Level: intermediate 2010 2011 Notes: This sets both the function for function evaluations and the function used to compute Jacobians via finite differences if no Jacobian 2012 computer is provided with DMSetJacobian(). Canceling cancels the function, but not the function used to compute the Jacobian. 2013 2014 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), DMSetInitialGuess(), 2015 DMSetJacobian() 2016 2017 @*/ 2018 PetscErrorCode DMSetFunction(DM dm,PetscErrorCode (*f)(DM,Vec,Vec)) 2019 { 2020 PetscFunctionBegin; 2021 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2022 dm->ops->function = f; 2023 if (f) { 2024 dm->ops->functionj = f; 2025 } 2026 PetscFunctionReturn(0); 2027 } 2028 2029 #undef __FUNCT__ 2030 #define __FUNCT__ "DMSetJacobian" 2031 /*@C 2032 DMSetJacobian - sets a function to compute the matrix entries for the KSP solver or Jacobian for SNES 2033 2034 Logically Collective on DM 2035 2036 Input Parameter: 2037 + dm - the DM object to destroy 2038 - f - the function to compute the matrix entries 2039 2040 Level: intermediate 2041 2042 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), DMSetInitialGuess(), 2043 DMSetFunction() 2044 2045 @*/ 2046 PetscErrorCode DMSetJacobian(DM dm,PetscErrorCode (*f)(DM,Vec,Mat,Mat,MatStructure*)) 2047 { 2048 PetscFunctionBegin; 2049 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2050 dm->ops->jacobian = f; 2051 PetscFunctionReturn(0); 2052 } 2053 2054 #undef __FUNCT__ 2055 #define __FUNCT__ "DMSetVariableBounds" 2056 /*@C 2057 DMSetVariableBounds - sets a function to compute the the lower and upper bound vectors for SNESVI. 2058 2059 Logically Collective on DM 2060 2061 Input Parameter: 2062 + dm - the DM object 2063 - f - the function that computes variable bounds used by SNESVI (use PETSC_NULL to cancel a previous function that was set) 2064 2065 Level: intermediate 2066 2067 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), DMSetInitialGuess(), 2068 DMSetJacobian() 2069 2070 @*/ 2071 PetscErrorCode DMSetVariableBounds(DM dm,PetscErrorCode (*f)(DM,Vec,Vec)) 2072 { 2073 PetscFunctionBegin; 2074 dm->ops->computevariablebounds = f; 2075 PetscFunctionReturn(0); 2076 } 2077 2078 #undef __FUNCT__ 2079 #define __FUNCT__ "DMHasVariableBounds" 2080 /*@ 2081 DMHasVariableBounds - does the DM object have a variable bounds function? 2082 2083 Not Collective 2084 2085 Input Parameter: 2086 . dm - the DM object to destroy 2087 2088 Output Parameter: 2089 . flg - PETSC_TRUE if the variable bounds function exists 2090 2091 Level: developer 2092 2093 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), DMSetFunction(), DMSetJacobian() 2094 2095 @*/ 2096 PetscErrorCode DMHasVariableBounds(DM dm,PetscBool *flg) 2097 { 2098 PetscFunctionBegin; 2099 *flg = (dm->ops->computevariablebounds) ? PETSC_TRUE : PETSC_FALSE; 2100 PetscFunctionReturn(0); 2101 } 2102 2103 #undef __FUNCT__ 2104 #define __FUNCT__ "DMComputeVariableBounds" 2105 /*@C 2106 DMComputeVariableBounds - compute variable bounds used by SNESVI. 2107 2108 Logically Collective on DM 2109 2110 Input Parameters: 2111 + dm - the DM object to destroy 2112 - x - current solution at which the bounds are computed 2113 2114 Output parameters: 2115 + xl - lower bound 2116 - xu - upper bound 2117 2118 Level: intermediate 2119 2120 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), DMSetInitialGuess(), 2121 DMSetFunction(), DMSetVariableBounds() 2122 2123 @*/ 2124 PetscErrorCode DMComputeVariableBounds(DM dm, Vec xl, Vec xu) 2125 { 2126 PetscErrorCode ierr; 2127 PetscFunctionBegin; 2128 PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 2129 PetscValidHeaderSpecific(xu,VEC_CLASSID,2); 2130 if(dm->ops->computevariablebounds) { 2131 ierr = (*dm->ops->computevariablebounds)(dm, xl,xu); CHKERRQ(ierr); 2132 } 2133 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "This DM is incapable of computing variable bounds."); 2134 PetscFunctionReturn(0); 2135 } 2136 2137 #undef __FUNCT__ 2138 #define __FUNCT__ "DMComputeInitialGuess" 2139 /*@ 2140 DMComputeInitialGuess - computes an initial guess vector entries for the KSP solvers 2141 2142 Collective on DM 2143 2144 Input Parameter: 2145 + dm - the DM object to destroy 2146 - x - the vector to hold the initial guess values 2147 2148 Level: developer 2149 2150 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), DMSetRhs(), DMSetMat() 2151 2152 @*/ 2153 PetscErrorCode DMComputeInitialGuess(DM dm,Vec x) 2154 { 2155 PetscErrorCode ierr; 2156 PetscFunctionBegin; 2157 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2158 if (!dm->ops->initialguess) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"Need to provide function with DMSetInitialGuess()"); 2159 ierr = (*dm->ops->initialguess)(dm,x);CHKERRQ(ierr); 2160 PetscFunctionReturn(0); 2161 } 2162 2163 #undef __FUNCT__ 2164 #define __FUNCT__ "DMHasInitialGuess" 2165 /*@ 2166 DMHasInitialGuess - does the DM object have an initial guess function 2167 2168 Not Collective 2169 2170 Input Parameter: 2171 . dm - the DM object to destroy 2172 2173 Output Parameter: 2174 . flg - PETSC_TRUE if function exists 2175 2176 Level: developer 2177 2178 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), DMSetFunction(), DMSetJacobian() 2179 2180 @*/ 2181 PetscErrorCode DMHasInitialGuess(DM dm,PetscBool *flg) 2182 { 2183 PetscFunctionBegin; 2184 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2185 *flg = (dm->ops->initialguess) ? PETSC_TRUE : PETSC_FALSE; 2186 PetscFunctionReturn(0); 2187 } 2188 2189 #undef __FUNCT__ 2190 #define __FUNCT__ "DMHasFunction" 2191 /*@ 2192 DMHasFunction - does the DM object have a function 2193 2194 Not Collective 2195 2196 Input Parameter: 2197 . dm - the DM object to destroy 2198 2199 Output Parameter: 2200 . flg - PETSC_TRUE if function exists 2201 2202 Level: developer 2203 2204 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), DMSetFunction(), DMSetJacobian() 2205 2206 @*/ 2207 PetscErrorCode DMHasFunction(DM dm,PetscBool *flg) 2208 { 2209 PetscFunctionBegin; 2210 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2211 *flg = (dm->ops->function) ? PETSC_TRUE : PETSC_FALSE; 2212 PetscFunctionReturn(0); 2213 } 2214 2215 #undef __FUNCT__ 2216 #define __FUNCT__ "DMHasJacobian" 2217 /*@ 2218 DMHasJacobian - does the DM object have a matrix function 2219 2220 Not Collective 2221 2222 Input Parameter: 2223 . dm - the DM object to destroy 2224 2225 Output Parameter: 2226 . flg - PETSC_TRUE if function exists 2227 2228 Level: developer 2229 2230 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), DMSetFunction(), DMSetJacobian() 2231 2232 @*/ 2233 PetscErrorCode DMHasJacobian(DM dm,PetscBool *flg) 2234 { 2235 PetscFunctionBegin; 2236 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2237 *flg = (dm->ops->jacobian) ? PETSC_TRUE : PETSC_FALSE; 2238 PetscFunctionReturn(0); 2239 } 2240 2241 #undef __FUNCT__ 2242 #define __FUNCT__ "DMHasColoring" 2243 /*@ 2244 DMHasColoring - does the DM object have a method of providing a coloring? 2245 2246 Not Collective 2247 2248 Input Parameter: 2249 . dm - the DM object 2250 2251 Output Parameter: 2252 . flg - PETSC_TRUE if the DM has facilities for DMCreateColoring(). 2253 2254 Level: developer 2255 2256 .seealso DMHasFunction(), DMCreateColoring() 2257 2258 @*/ 2259 PetscErrorCode DMHasColoring(DM dm,PetscBool *flg) 2260 { 2261 PetscFunctionBegin; 2262 *flg = (dm->ops->getcoloring) ? PETSC_TRUE : PETSC_FALSE; 2263 PetscFunctionReturn(0); 2264 } 2265 2266 #undef __FUNCT__ 2267 #define __FUNCT__ "DMSetVec" 2268 /*@C 2269 DMSetVec - set the vector at which to compute residual, Jacobian and VI bounds, if the problem is nonlinear. 2270 2271 Collective on DM 2272 2273 Input Parameter: 2274 + dm - the DM object 2275 - x - location to compute residual and Jacobian, if PETSC_NULL is passed to those routines; will be PETSC_NULL for linear problems. 2276 2277 Level: developer 2278 2279 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), DMSetInitialGuess(), 2280 DMSetFunction(), DMSetJacobian(), DMSetVariableBounds() 2281 2282 @*/ 2283 PetscErrorCode DMSetVec(DM dm,Vec x) 2284 { 2285 PetscErrorCode ierr; 2286 PetscFunctionBegin; 2287 if (x) { 2288 if (!dm->x) { 2289 ierr = DMCreateGlobalVector(dm,&dm->x);CHKERRQ(ierr); 2290 } 2291 ierr = VecCopy(x,dm->x);CHKERRQ(ierr); 2292 } 2293 else if(dm->x) { 2294 ierr = VecDestroy(&dm->x); CHKERRQ(ierr); 2295 } 2296 PetscFunctionReturn(0); 2297 } 2298 2299 2300 #undef __FUNCT__ 2301 #define __FUNCT__ "DMComputeFunction" 2302 /*@ 2303 DMComputeFunction - computes the right hand side vector entries for the KSP solver or nonlinear function for SNES 2304 2305 Collective on DM 2306 2307 Input Parameter: 2308 + dm - the DM object to destroy 2309 . x - the location where the function is evaluationed, may be ignored for linear problems 2310 - b - the vector to hold the right hand side entries 2311 2312 Level: developer 2313 2314 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), DMSetInitialGuess(), 2315 DMSetJacobian() 2316 2317 @*/ 2318 PetscErrorCode DMComputeFunction(DM dm,Vec x,Vec b) 2319 { 2320 PetscErrorCode ierr; 2321 PetscFunctionBegin; 2322 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2323 if (!dm->ops->function) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_ARG_WRONGSTATE,"Need to provide function with DMSetFunction()"); 2324 PetscStackPush("DM user function"); 2325 ierr = (*dm->ops->function)(dm,x,b);CHKERRQ(ierr); 2326 PetscStackPop; 2327 PetscFunctionReturn(0); 2328 } 2329 2330 2331 2332 #undef __FUNCT__ 2333 #define __FUNCT__ "DMComputeJacobian" 2334 /*@ 2335 DMComputeJacobian - compute the matrix entries for the solver 2336 2337 Collective on DM 2338 2339 Input Parameter: 2340 + dm - the DM object 2341 . x - location to compute Jacobian at; will be PETSC_NULL for linear problems, for nonlinear problems if not provided then pulled from DM 2342 . A - matrix that defines the operator for the linear solve 2343 - B - the matrix used to construct the preconditioner 2344 2345 Level: developer 2346 2347 .seealso DMView(), DMCreateGlobalVector(), DMCreateInterpolation(), DMCreateColoring(), DMCreateMatrix(), DMGetApplicationContext(), DMSetInitialGuess(), 2348 DMSetFunction() 2349 2350 @*/ 2351 PetscErrorCode DMComputeJacobian(DM dm,Vec x,Mat A,Mat B,MatStructure *stflag) 2352 { 2353 PetscErrorCode ierr; 2354 2355 PetscFunctionBegin; 2356 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2357 if (!dm->ops->jacobian) { 2358 ISColoring coloring; 2359 MatFDColoring fd; 2360 const MatType mtype; 2361 2362 ierr = PetscObjectGetType((PetscObject)B,&mtype);CHKERRQ(ierr); 2363 ierr = DMCreateColoring(dm,dm->coloringtype,mtype,&coloring);CHKERRQ(ierr); 2364 ierr = MatFDColoringCreate(B,coloring,&fd);CHKERRQ(ierr); 2365 ierr = ISColoringDestroy(&coloring);CHKERRQ(ierr); 2366 ierr = MatFDColoringSetFunction(fd,(PetscErrorCode (*)(void))dm->ops->functionj,dm);CHKERRQ(ierr); 2367 ierr = PetscObjectSetOptionsPrefix((PetscObject)fd,((PetscObject)dm)->prefix);CHKERRQ(ierr); 2368 ierr = MatFDColoringSetFromOptions(fd);CHKERRQ(ierr); 2369 2370 dm->fd = fd; 2371 dm->ops->jacobian = DMComputeJacobianDefault; 2372 2373 /* don't know why this is needed */ 2374 ierr = PetscObjectDereference((PetscObject)dm);CHKERRQ(ierr); 2375 } 2376 if (!x) x = dm->x; 2377 ierr = (*dm->ops->jacobian)(dm,x,A,B,stflag);CHKERRQ(ierr); 2378 2379 /* if matrix depends on x; i.e. nonlinear problem, keep copy of input vector since needed by multigrid methods to generate coarse grid matrices */ 2380 if (x) { 2381 if (!dm->x) { 2382 ierr = DMCreateGlobalVector(dm,&dm->x);CHKERRQ(ierr); 2383 } 2384 ierr = VecCopy(x,dm->x);CHKERRQ(ierr); 2385 } 2386 if (A != B) { 2387 ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2388 ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2389 } 2390 PetscFunctionReturn(0); 2391 } 2392 2393 2394 PetscFList DMList = PETSC_NULL; 2395 PetscBool DMRegisterAllCalled = PETSC_FALSE; 2396 2397 #undef __FUNCT__ 2398 #define __FUNCT__ "DMSetType" 2399 /*@C 2400 DMSetType - Builds a DM, for a particular DM implementation. 2401 2402 Collective on DM 2403 2404 Input Parameters: 2405 + dm - The DM object 2406 - method - The name of the DM type 2407 2408 Options Database Key: 2409 . -dm_type <type> - Sets the DM type; use -help for a list of available types 2410 2411 Notes: 2412 See "petsc/include/petscdm.h" for available DM types (for instance, DM1D, DM2D, or DM3D). 2413 2414 Level: intermediate 2415 2416 .keywords: DM, set, type 2417 .seealso: DMGetType(), DMCreate() 2418 @*/ 2419 PetscErrorCode DMSetType(DM dm, const DMType method) 2420 { 2421 PetscErrorCode (*r)(DM); 2422 PetscBool match; 2423 PetscErrorCode ierr; 2424 2425 PetscFunctionBegin; 2426 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 2427 ierr = PetscObjectTypeCompare((PetscObject) dm, method, &match);CHKERRQ(ierr); 2428 if (match) PetscFunctionReturn(0); 2429 2430 if (!DMRegisterAllCalled) {ierr = DMRegisterAll(PETSC_NULL);CHKERRQ(ierr);} 2431 ierr = PetscFListFind(DMList, ((PetscObject)dm)->comm, method,PETSC_TRUE,(void (**)(void)) &r);CHKERRQ(ierr); 2432 if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DM type: %s", method); 2433 2434 if (dm->ops->destroy) { 2435 ierr = (*dm->ops->destroy)(dm);CHKERRQ(ierr); 2436 dm->ops->destroy = PETSC_NULL; 2437 } 2438 ierr = (*r)(dm);CHKERRQ(ierr); 2439 ierr = PetscObjectChangeTypeName((PetscObject)dm,method);CHKERRQ(ierr); 2440 PetscFunctionReturn(0); 2441 } 2442 2443 #undef __FUNCT__ 2444 #define __FUNCT__ "DMGetType" 2445 /*@C 2446 DMGetType - Gets the DM type name (as a string) from the DM. 2447 2448 Not Collective 2449 2450 Input Parameter: 2451 . dm - The DM 2452 2453 Output Parameter: 2454 . type - The DM type name 2455 2456 Level: intermediate 2457 2458 .keywords: DM, get, type, name 2459 .seealso: DMSetType(), DMCreate() 2460 @*/ 2461 PetscErrorCode DMGetType(DM dm, const DMType *type) 2462 { 2463 PetscErrorCode ierr; 2464 2465 PetscFunctionBegin; 2466 PetscValidHeaderSpecific(dm, DM_CLASSID,1); 2467 PetscValidCharPointer(type,2); 2468 if (!DMRegisterAllCalled) { 2469 ierr = DMRegisterAll(PETSC_NULL);CHKERRQ(ierr); 2470 } 2471 *type = ((PetscObject)dm)->type_name; 2472 PetscFunctionReturn(0); 2473 } 2474 2475 #undef __FUNCT__ 2476 #define __FUNCT__ "DMConvert" 2477 /*@C 2478 DMConvert - Converts a DM to another DM, either of the same or different type. 2479 2480 Collective on DM 2481 2482 Input Parameters: 2483 + dm - the DM 2484 - newtype - new DM type (use "same" for the same type) 2485 2486 Output Parameter: 2487 . M - pointer to new DM 2488 2489 Notes: 2490 Cannot be used to convert a sequential DM to parallel or parallel to sequential, 2491 the MPI communicator of the generated DM is always the same as the communicator 2492 of the input DM. 2493 2494 Level: intermediate 2495 2496 .seealso: DMCreate() 2497 @*/ 2498 PetscErrorCode DMConvert(DM dm, const DMType newtype, DM *M) 2499 { 2500 DM B; 2501 char convname[256]; 2502 PetscBool sametype, issame; 2503 PetscErrorCode ierr; 2504 2505 PetscFunctionBegin; 2506 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2507 PetscValidType(dm,1); 2508 PetscValidPointer(M,3); 2509 ierr = PetscObjectTypeCompare((PetscObject) dm, newtype, &sametype);CHKERRQ(ierr); 2510 ierr = PetscStrcmp(newtype, "same", &issame);CHKERRQ(ierr); 2511 { 2512 PetscErrorCode (*conv)(DM, const DMType, DM *) = PETSC_NULL; 2513 2514 /* 2515 Order of precedence: 2516 1) See if a specialized converter is known to the current DM. 2517 2) See if a specialized converter is known to the desired DM class. 2518 3) See if a good general converter is registered for the desired class 2519 4) See if a good general converter is known for the current matrix. 2520 5) Use a really basic converter. 2521 */ 2522 2523 /* 1) See if a specialized converter is known to the current DM and the desired class */ 2524 ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr); 2525 ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr); 2526 ierr = PetscStrcat(convname,"_");CHKERRQ(ierr); 2527 ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr); 2528 ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr); 2529 ierr = PetscObjectQueryFunction((PetscObject)dm,convname,(void (**)(void))&conv);CHKERRQ(ierr); 2530 if (conv) goto foundconv; 2531 2532 /* 2) See if a specialized converter is known to the desired DM class. */ 2533 ierr = DMCreate(((PetscObject) dm)->comm, &B);CHKERRQ(ierr); 2534 ierr = DMSetType(B, newtype);CHKERRQ(ierr); 2535 ierr = PetscStrcpy(convname,"DMConvert_");CHKERRQ(ierr); 2536 ierr = PetscStrcat(convname,((PetscObject) dm)->type_name);CHKERRQ(ierr); 2537 ierr = PetscStrcat(convname,"_");CHKERRQ(ierr); 2538 ierr = PetscStrcat(convname,newtype);CHKERRQ(ierr); 2539 ierr = PetscStrcat(convname,"_C");CHKERRQ(ierr); 2540 ierr = PetscObjectQueryFunction((PetscObject)B,convname,(void (**)(void))&conv);CHKERRQ(ierr); 2541 if (conv) { 2542 ierr = DMDestroy(&B);CHKERRQ(ierr); 2543 goto foundconv; 2544 } 2545 2546 #if 0 2547 /* 3) See if a good general converter is registered for the desired class */ 2548 conv = B->ops->convertfrom; 2549 ierr = DMDestroy(&B);CHKERRQ(ierr); 2550 if (conv) goto foundconv; 2551 2552 /* 4) See if a good general converter is known for the current matrix */ 2553 if (dm->ops->convert) { 2554 conv = dm->ops->convert; 2555 } 2556 if (conv) goto foundconv; 2557 #endif 2558 2559 /* 5) Use a really basic converter. */ 2560 SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_SUP, "No conversion possible between DM types %s and %s", ((PetscObject) dm)->type_name, newtype); 2561 2562 foundconv: 2563 ierr = PetscLogEventBegin(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 2564 ierr = (*conv)(dm,newtype,M);CHKERRQ(ierr); 2565 ierr = PetscLogEventEnd(DM_Convert,dm,0,0,0);CHKERRQ(ierr); 2566 } 2567 ierr = PetscObjectStateIncrease((PetscObject) *M);CHKERRQ(ierr); 2568 PetscFunctionReturn(0); 2569 } 2570 2571 /*--------------------------------------------------------------------------------------------------------------------*/ 2572 2573 #undef __FUNCT__ 2574 #define __FUNCT__ "DMRegister" 2575 /*@C 2576 DMRegister - See DMRegisterDynamic() 2577 2578 Level: advanced 2579 @*/ 2580 PetscErrorCode DMRegister(const char sname[], const char path[], const char name[], PetscErrorCode (*function)(DM)) 2581 { 2582 char fullname[PETSC_MAX_PATH_LEN]; 2583 PetscErrorCode ierr; 2584 2585 PetscFunctionBegin; 2586 ierr = PetscStrcpy(fullname, path);CHKERRQ(ierr); 2587 ierr = PetscStrcat(fullname, ":");CHKERRQ(ierr); 2588 ierr = PetscStrcat(fullname, name);CHKERRQ(ierr); 2589 ierr = PetscFListAdd(&DMList, sname, fullname, (void (*)(void)) function);CHKERRQ(ierr); 2590 PetscFunctionReturn(0); 2591 } 2592 2593 2594 /*--------------------------------------------------------------------------------------------------------------------*/ 2595 #undef __FUNCT__ 2596 #define __FUNCT__ "DMRegisterDestroy" 2597 /*@C 2598 DMRegisterDestroy - Frees the list of DM methods that were registered by DMRegister()/DMRegisterDynamic(). 2599 2600 Not Collective 2601 2602 Level: advanced 2603 2604 .keywords: DM, register, destroy 2605 .seealso: DMRegister(), DMRegisterAll(), DMRegisterDynamic() 2606 @*/ 2607 PetscErrorCode DMRegisterDestroy(void) 2608 { 2609 PetscErrorCode ierr; 2610 2611 PetscFunctionBegin; 2612 ierr = PetscFListDestroy(&DMList);CHKERRQ(ierr); 2613 DMRegisterAllCalled = PETSC_FALSE; 2614 PetscFunctionReturn(0); 2615 } 2616 2617 #if defined(PETSC_HAVE_MATLAB_ENGINE) 2618 #include <mex.h> 2619 2620 typedef struct {char *funcname; char *jacname; mxArray *ctx;} DMMatlabContext; 2621 2622 #undef __FUNCT__ 2623 #define __FUNCT__ "DMComputeFunction_Matlab" 2624 /* 2625 DMComputeFunction_Matlab - Calls the function that has been set with 2626 DMSetFunctionMatlab(). 2627 2628 For linear problems x is null 2629 2630 .seealso: DMSetFunction(), DMGetFunction() 2631 */ 2632 PetscErrorCode DMComputeFunction_Matlab(DM dm,Vec x,Vec y) 2633 { 2634 PetscErrorCode ierr; 2635 DMMatlabContext *sctx; 2636 int nlhs = 1,nrhs = 4; 2637 mxArray *plhs[1],*prhs[4]; 2638 long long int lx = 0,ly = 0,ls = 0; 2639 2640 PetscFunctionBegin; 2641 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2642 PetscValidHeaderSpecific(y,VEC_CLASSID,3); 2643 PetscCheckSameComm(dm,1,y,3); 2644 2645 /* call Matlab function in ctx with arguments x and y */ 2646 ierr = DMGetApplicationContext(dm,&sctx);CHKERRQ(ierr); 2647 ierr = PetscMemcpy(&ls,&dm,sizeof(dm));CHKERRQ(ierr); 2648 ierr = PetscMemcpy(&lx,&x,sizeof(x));CHKERRQ(ierr); 2649 ierr = PetscMemcpy(&ly,&y,sizeof(y));CHKERRQ(ierr); 2650 prhs[0] = mxCreateDoubleScalar((double)ls); 2651 prhs[1] = mxCreateDoubleScalar((double)lx); 2652 prhs[2] = mxCreateDoubleScalar((double)ly); 2653 prhs[3] = mxCreateString(sctx->funcname); 2654 ierr = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscDMComputeFunctionInternal");CHKERRQ(ierr); 2655 ierr = mxGetScalar(plhs[0]);CHKERRQ(ierr); 2656 mxDestroyArray(prhs[0]); 2657 mxDestroyArray(prhs[1]); 2658 mxDestroyArray(prhs[2]); 2659 mxDestroyArray(prhs[3]); 2660 mxDestroyArray(plhs[0]); 2661 PetscFunctionReturn(0); 2662 } 2663 2664 2665 #undef __FUNCT__ 2666 #define __FUNCT__ "DMSetFunctionMatlab" 2667 /* 2668 DMSetFunctionMatlab - Sets the function evaluation routine 2669 2670 */ 2671 PetscErrorCode DMSetFunctionMatlab(DM dm,const char *func) 2672 { 2673 PetscErrorCode ierr; 2674 DMMatlabContext *sctx; 2675 2676 PetscFunctionBegin; 2677 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2678 /* currently sctx is memory bleed */ 2679 ierr = DMGetApplicationContext(dm,&sctx);CHKERRQ(ierr); 2680 if (!sctx) { 2681 ierr = PetscMalloc(sizeof(DMMatlabContext),&sctx);CHKERRQ(ierr); 2682 } 2683 ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr); 2684 ierr = DMSetApplicationContext(dm,sctx);CHKERRQ(ierr); 2685 ierr = DMSetFunction(dm,DMComputeFunction_Matlab);CHKERRQ(ierr); 2686 PetscFunctionReturn(0); 2687 } 2688 2689 #undef __FUNCT__ 2690 #define __FUNCT__ "DMComputeJacobian_Matlab" 2691 /* 2692 DMComputeJacobian_Matlab - Calls the function that has been set with 2693 DMSetJacobianMatlab(). 2694 2695 For linear problems x is null 2696 2697 .seealso: DMSetFunction(), DMGetFunction() 2698 */ 2699 PetscErrorCode DMComputeJacobian_Matlab(DM dm,Vec x,Mat A,Mat B,MatStructure *str) 2700 { 2701 PetscErrorCode ierr; 2702 DMMatlabContext *sctx; 2703 int nlhs = 2,nrhs = 5; 2704 mxArray *plhs[2],*prhs[5]; 2705 long long int lx = 0,lA = 0,lB = 0,ls = 0; 2706 2707 PetscFunctionBegin; 2708 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2709 PetscValidHeaderSpecific(A,MAT_CLASSID,3); 2710 2711 /* call MATLAB function in ctx with arguments x, A, and B */ 2712 ierr = DMGetApplicationContext(dm,&sctx);CHKERRQ(ierr); 2713 ierr = PetscMemcpy(&ls,&dm,sizeof(dm));CHKERRQ(ierr); 2714 ierr = PetscMemcpy(&lx,&x,sizeof(x));CHKERRQ(ierr); 2715 ierr = PetscMemcpy(&lA,&A,sizeof(A));CHKERRQ(ierr); 2716 ierr = PetscMemcpy(&lB,&B,sizeof(B));CHKERRQ(ierr); 2717 prhs[0] = mxCreateDoubleScalar((double)ls); 2718 prhs[1] = mxCreateDoubleScalar((double)lx); 2719 prhs[2] = mxCreateDoubleScalar((double)lA); 2720 prhs[3] = mxCreateDoubleScalar((double)lB); 2721 prhs[4] = mxCreateString(sctx->jacname); 2722 ierr = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscDMComputeJacobianInternal");CHKERRQ(ierr); 2723 *str = (MatStructure) mxGetScalar(plhs[0]); 2724 ierr = (PetscInt) mxGetScalar(plhs[1]);CHKERRQ(ierr); 2725 mxDestroyArray(prhs[0]); 2726 mxDestroyArray(prhs[1]); 2727 mxDestroyArray(prhs[2]); 2728 mxDestroyArray(prhs[3]); 2729 mxDestroyArray(prhs[4]); 2730 mxDestroyArray(plhs[0]); 2731 mxDestroyArray(plhs[1]); 2732 PetscFunctionReturn(0); 2733 } 2734 2735 2736 #undef __FUNCT__ 2737 #define __FUNCT__ "DMSetJacobianMatlab" 2738 /* 2739 DMSetJacobianMatlab - Sets the Jacobian function evaluation routine 2740 2741 */ 2742 PetscErrorCode DMSetJacobianMatlab(DM dm,const char *func) 2743 { 2744 PetscErrorCode ierr; 2745 DMMatlabContext *sctx; 2746 2747 PetscFunctionBegin; 2748 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 2749 /* currently sctx is memory bleed */ 2750 ierr = DMGetApplicationContext(dm,&sctx);CHKERRQ(ierr); 2751 if (!sctx) { 2752 ierr = PetscMalloc(sizeof(DMMatlabContext),&sctx);CHKERRQ(ierr); 2753 } 2754 ierr = PetscStrallocpy(func,&sctx->jacname);CHKERRQ(ierr); 2755 ierr = DMSetApplicationContext(dm,sctx);CHKERRQ(ierr); 2756 ierr = DMSetJacobian(dm,DMComputeJacobian_Matlab);CHKERRQ(ierr); 2757 PetscFunctionReturn(0); 2758 } 2759 #endif 2760 2761 #undef __FUNCT__ 2762 #define __FUNCT__ "DMLoad" 2763 /*@C 2764 DMLoad - Loads a DM that has been stored in binary or HDF5 format 2765 with DMView(). 2766 2767 Collective on PetscViewer 2768 2769 Input Parameters: 2770 + newdm - the newly loaded DM, this needs to have been created with DMCreate() or 2771 some related function before a call to DMLoad(). 2772 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or 2773 HDF5 file viewer, obtained from PetscViewerHDF5Open() 2774 2775 Level: intermediate 2776 2777 Notes: 2778 Defaults to the DM DA. 2779 2780 Notes for advanced users: 2781 Most users should not need to know the details of the binary storage 2782 format, since DMLoad() and DMView() completely hide these details. 2783 But for anyone who's interested, the standard binary matrix storage 2784 format is 2785 .vb 2786 has not yet been determined 2787 .ve 2788 2789 In addition, PETSc automatically does the byte swapping for 2790 machines that store the bytes reversed, e.g. DEC alpha, freebsd, 2791 linux, Windows and the paragon; thus if you write your own binary 2792 read/write routines you have to swap the bytes; see PetscBinaryRead() 2793 and PetscBinaryWrite() to see how this may be done. 2794 2795 Concepts: vector^loading from file 2796 2797 .seealso: PetscViewerBinaryOpen(), DMView(), MatLoad(), VecLoad() 2798 @*/ 2799 PetscErrorCode DMLoad(DM newdm, PetscViewer viewer) 2800 { 2801 PetscErrorCode ierr; 2802 2803 PetscFunctionBegin; 2804 PetscValidHeaderSpecific(newdm,DM_CLASSID,1); 2805 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 2806 2807 if (!((PetscObject)newdm)->type_name) { 2808 ierr = DMSetType(newdm, DMDA);CHKERRQ(ierr); 2809 } 2810 ierr = (*newdm->ops->load)(newdm,viewer);CHKERRQ(ierr); 2811 PetscFunctionReturn(0); 2812 } 2813 2814 /******************************** FEM Support **********************************/ 2815 2816 #undef __FUNCT__ 2817 #define __FUNCT__ "DMPrintCellVector" 2818 PetscErrorCode DMPrintCellVector(PetscInt c, const char name[], PetscInt len, const PetscScalar x[]) { 2819 PetscInt f; 2820 PetscErrorCode ierr; 2821 2822 PetscFunctionBegin; 2823 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 2824 for(f = 0; f < len; ++f) { 2825 ierr = PetscPrintf(PETSC_COMM_SELF, " | %G |\n", PetscRealPart(x[f]));CHKERRQ(ierr); 2826 } 2827 PetscFunctionReturn(0); 2828 } 2829 2830 #undef __FUNCT__ 2831 #define __FUNCT__ "DMPrintCellMatrix" 2832 PetscErrorCode DMPrintCellMatrix(PetscInt c, const char name[], PetscInt rows, PetscInt cols, const PetscScalar A[]) { 2833 PetscInt f, g; 2834 PetscErrorCode ierr; 2835 2836 PetscFunctionBegin; 2837 ierr = PetscPrintf(PETSC_COMM_SELF, "Cell %D Element %s\n", c, name);CHKERRQ(ierr); 2838 for(f = 0; f < rows; ++f) { 2839 ierr = PetscPrintf(PETSC_COMM_SELF, " |");CHKERRQ(ierr); 2840 for(g = 0; g < cols; ++g) { 2841 ierr = PetscPrintf(PETSC_COMM_SELF, " % 9.5G", PetscRealPart(A[f*cols+g]));CHKERRQ(ierr); 2842 } 2843 ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr); 2844 } 2845 PetscFunctionReturn(0); 2846 } 2847 2848 #undef __FUNCT__ 2849 #define __FUNCT__ "DMGetLocalFunction" 2850 /*@C 2851 DMGetLocalFunction - Get the local residual function from this DM 2852 2853 Not collective 2854 2855 Input Parameter: 2856 . dm - The DM 2857 2858 Output Parameter: 2859 . lf - The local residual function 2860 2861 Calling sequence of lf: 2862 $ lf (SNES snes, Vec x, Vec f, void *ctx); 2863 2864 + snes - the SNES context 2865 . x - local vector with the state at which to evaluate residual 2866 . f - local vector to put residual in 2867 - ctx - optional user-defined function context 2868 2869 Level: intermediate 2870 2871 .seealso DMSetLocalFunction(), DMGetLocalJacobian(), DMSetLocalJacobian() 2872 @*/ 2873 PetscErrorCode DMGetLocalFunction(DM dm, PetscErrorCode (**lf)(DM, Vec, Vec, void *)) 2874 { 2875 PetscFunctionBegin; 2876 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2877 if (lf) *lf = dm->lf; 2878 PetscFunctionReturn(0); 2879 } 2880 2881 #undef __FUNCT__ 2882 #define __FUNCT__ "DMSetLocalFunction" 2883 /*@C 2884 DMSetLocalFunction - Set the local residual function from this DM 2885 2886 Not collective 2887 2888 Input Parameters: 2889 + dm - The DM 2890 - lf - The local residual function 2891 2892 Calling sequence of lf: 2893 $ lf (SNES snes, Vec x, Vec f, void *ctx); 2894 2895 + snes - the SNES context 2896 . x - local vector with the state at which to evaluate residual 2897 . f - local vector to put residual in 2898 - ctx - optional user-defined function context 2899 2900 Level: intermediate 2901 2902 .seealso DMGetLocalFunction(), DMGetLocalJacobian(), DMSetLocalJacobian() 2903 @*/ 2904 PetscErrorCode DMSetLocalFunction(DM dm, PetscErrorCode (*lf)(DM, Vec, Vec, void *)) 2905 { 2906 PetscFunctionBegin; 2907 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2908 dm->lf = lf; 2909 PetscFunctionReturn(0); 2910 } 2911 2912 #undef __FUNCT__ 2913 #define __FUNCT__ "DMGetLocalJacobian" 2914 /*@C 2915 DMGetLocalJacobian - Get the local Jacobian function from this DM 2916 2917 Not collective 2918 2919 Input Parameter: 2920 . dm - The DM 2921 2922 Output Parameter: 2923 . lj - The local Jacobian function 2924 2925 Calling sequence of lj: 2926 $ lj (SNES snes, Vec x, Mat J, Mat M, void *ctx); 2927 2928 + snes - the SNES context 2929 . x - local vector with the state at which to evaluate residual 2930 . J - matrix to put Jacobian in 2931 . M - matrix to use for defining Jacobian preconditioner 2932 - ctx - optional user-defined function context 2933 2934 Level: intermediate 2935 2936 .seealso DMSetLocalJacobian(), DMGetLocalFunction(), DMSetLocalFunction() 2937 @*/ 2938 PetscErrorCode DMGetLocalJacobian(DM dm, PetscErrorCode (**lj)(DM, Vec, Mat, Mat, void *)) 2939 { 2940 PetscFunctionBegin; 2941 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2942 if (lj) *lj = dm->lj; 2943 PetscFunctionReturn(0); 2944 } 2945 2946 #undef __FUNCT__ 2947 #define __FUNCT__ "DMSetLocalJacobian" 2948 /*@C 2949 DMSetLocalJacobian - Set the local Jacobian function from this DM 2950 2951 Not collective 2952 2953 Input Parameters: 2954 + dm - The DM 2955 - lj - The local Jacobian function 2956 2957 Calling sequence of lj: 2958 $ lj (SNES snes, Vec x, Mat J, Mat M, void *ctx); 2959 2960 + snes - the SNES context 2961 . x - local vector with the state at which to evaluate residual 2962 . J - matrix to put Jacobian in 2963 . M - matrix to use for defining Jacobian preconditioner 2964 - ctx - optional user-defined function context 2965 2966 Level: intermediate 2967 2968 .seealso DMGetLocalJacobian(), DMGetLocalFunction(), DMSetLocalFunction() 2969 @*/ 2970 PetscErrorCode DMSetLocalJacobian(DM dm, PetscErrorCode (*lj)(DM, Vec, Mat, Mat, void *)) 2971 { 2972 PetscFunctionBegin; 2973 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2974 dm->lj = lj; 2975 PetscFunctionReturn(0); 2976 } 2977 2978 #undef __FUNCT__ 2979 #define __FUNCT__ "DMGetDefaultSection" 2980 /*@ 2981 DMGetDefaultSection - Get the PetscSection encoding the local data layout for the DM. 2982 2983 Input Parameter: 2984 . dm - The DM 2985 2986 Output Parameter: 2987 . section - The PetscSection 2988 2989 Level: intermediate 2990 2991 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 2992 2993 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection() 2994 @*/ 2995 PetscErrorCode DMGetDefaultSection(DM dm, PetscSection *section) { 2996 PetscFunctionBegin; 2997 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2998 PetscValidPointer(section, 2); 2999 *section = dm->defaultSection; 3000 PetscFunctionReturn(0); 3001 } 3002 3003 #undef __FUNCT__ 3004 #define __FUNCT__ "DMSetDefaultSection" 3005 /*@ 3006 DMSetDefaultSection - Set the PetscSection encoding the local data layout for the DM. 3007 3008 Input Parameters: 3009 + dm - The DM 3010 - section - The PetscSection 3011 3012 Level: intermediate 3013 3014 Note: Any existing Section will be destroyed 3015 3016 .seealso: DMSetDefaultSection(), DMGetDefaultGlobalSection() 3017 @*/ 3018 PetscErrorCode DMSetDefaultSection(DM dm, PetscSection section) { 3019 PetscInt numFields; 3020 PetscInt f; 3021 PetscErrorCode ierr; 3022 3023 PetscFunctionBegin; 3024 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3025 ierr = PetscSectionDestroy(&dm->defaultSection);CHKERRQ(ierr); 3026 ierr = PetscSectionDestroy(&dm->defaultGlobalSection);CHKERRQ(ierr); 3027 dm->defaultSection = section; 3028 ierr = PetscSectionGetNumFields(dm->defaultSection, &numFields);CHKERRQ(ierr); 3029 if (numFields) { 3030 ierr = DMSetNumFields(dm, numFields);CHKERRQ(ierr); 3031 for(f = 0; f < numFields; ++f) { 3032 const char *name; 3033 3034 ierr = PetscSectionGetFieldName(dm->defaultSection, f, &name);CHKERRQ(ierr); 3035 ierr = PetscObjectSetName(dm->fields[f], name);CHKERRQ(ierr); 3036 } 3037 } 3038 PetscFunctionReturn(0); 3039 } 3040 3041 #undef __FUNCT__ 3042 #define __FUNCT__ "DMGetDefaultGlobalSection" 3043 /*@ 3044 DMGetDefaultGlobalSection - Get the PetscSection encoding the global data layout for the DM. 3045 3046 Input Parameter: 3047 . dm - The DM 3048 3049 Output Parameter: 3050 . section - The PetscSection 3051 3052 Level: intermediate 3053 3054 Note: This gets a borrowed reference, so the user should not destroy this PetscSection. 3055 3056 .seealso: DMSetDefaultSection(), DMGetDefaultSection() 3057 @*/ 3058 PetscErrorCode DMGetDefaultGlobalSection(DM dm, PetscSection *section) { 3059 PetscErrorCode ierr; 3060 3061 PetscFunctionBegin; 3062 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3063 PetscValidPointer(section, 2); 3064 if (!dm->defaultGlobalSection) { 3065 ierr = PetscSectionCreateGlobalSection(dm->defaultSection, dm->sf, &dm->defaultGlobalSection);CHKERRQ(ierr); 3066 } 3067 *section = dm->defaultGlobalSection; 3068 PetscFunctionReturn(0); 3069 } 3070 3071 #undef __FUNCT__ 3072 #define __FUNCT__ "DMGetDefaultSF" 3073 /*@ 3074 DMGetDefaultSF - Get the PetscSF encoding the parallel dof overlap for the DM. If it has not been set, 3075 it is created from the default PetscSection layouts in the DM. 3076 3077 Input Parameter: 3078 . dm - The DM 3079 3080 Output Parameter: 3081 . sf - The PetscSF 3082 3083 Level: intermediate 3084 3085 Note: This gets a borrowed reference, so the user should not destroy this PetscSF. 3086 3087 .seealso: DMSetDefaultSF(), DMCreateDefaultSF() 3088 @*/ 3089 PetscErrorCode DMGetDefaultSF(DM dm, PetscSF *sf) { 3090 PetscInt nroots; 3091 PetscErrorCode ierr; 3092 3093 PetscFunctionBegin; 3094 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3095 PetscValidPointer(sf, 2); 3096 ierr = PetscSFGetGraph(dm->defaultSF, &nroots, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 3097 if (nroots < 0) { 3098 PetscSection section, gSection; 3099 3100 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 3101 if (section) { 3102 ierr = DMGetDefaultGlobalSection(dm, &gSection);CHKERRQ(ierr); 3103 ierr = DMCreateDefaultSF(dm, section, gSection);CHKERRQ(ierr); 3104 } else { 3105 *sf = PETSC_NULL; 3106 PetscFunctionReturn(0); 3107 } 3108 } 3109 *sf = dm->defaultSF; 3110 PetscFunctionReturn(0); 3111 } 3112 3113 #undef __FUNCT__ 3114 #define __FUNCT__ "DMSetDefaultSF" 3115 /*@ 3116 DMSetDefaultSF - Set the PetscSF encoding the parallel dof overlap for the DM 3117 3118 Input Parameters: 3119 + dm - The DM 3120 - sf - The PetscSF 3121 3122 Level: intermediate 3123 3124 Note: Any previous SF is destroyed 3125 3126 .seealso: DMGetDefaultSF(), DMCreateDefaultSF() 3127 @*/ 3128 PetscErrorCode DMSetDefaultSF(DM dm, PetscSF sf) { 3129 PetscErrorCode ierr; 3130 3131 PetscFunctionBegin; 3132 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3133 PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 2); 3134 ierr = PetscSFDestroy(&dm->defaultSF);CHKERRQ(ierr); 3135 dm->defaultSF = sf; 3136 PetscFunctionReturn(0); 3137 } 3138 3139 #undef __FUNCT__ 3140 #define __FUNCT__ "DMCreateDefaultSF" 3141 /*@C 3142 DMCreateDefaultSF - Create the PetscSF encoding the parallel dof overlap for the DM based upon the PetscSections 3143 describing the data layout. 3144 3145 Input Parameters: 3146 + dm - The DM 3147 . localSection - PetscSection describing the local data layout 3148 - globalSection - PetscSection describing the global data layout 3149 3150 Level: intermediate 3151 3152 .seealso: DMGetDefaultSF(), DMSetDefaultSF() 3153 @*/ 3154 PetscErrorCode DMCreateDefaultSF(DM dm, PetscSection localSection, PetscSection globalSection) 3155 { 3156 MPI_Comm comm = ((PetscObject) dm)->comm; 3157 PetscLayout layout; 3158 const PetscInt *ranges; 3159 PetscInt *local; 3160 PetscSFNode *remote; 3161 PetscInt pStart, pEnd, p, nroots, nleaves, l; 3162 PetscMPIInt size, rank; 3163 PetscErrorCode ierr; 3164 3165 PetscFunctionBegin; 3166 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3167 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 3168 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3169 ierr = PetscSectionGetChart(globalSection, &pStart, &pEnd);CHKERRQ(ierr); 3170 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &nroots);CHKERRQ(ierr); 3171 ierr = PetscLayoutCreate(comm, &layout);CHKERRQ(ierr); 3172 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3173 ierr = PetscLayoutSetLocalSize(layout, nroots);CHKERRQ(ierr); 3174 ierr = PetscLayoutSetUp(layout);CHKERRQ(ierr); 3175 ierr = PetscLayoutGetRanges(layout, &ranges);CHKERRQ(ierr); 3176 for(p = pStart, nleaves = 0; p < pEnd; ++p) { 3177 PetscInt dof, cdof; 3178 3179 ierr = PetscSectionGetDof(globalSection, p, &dof);CHKERRQ(ierr); 3180 ierr = PetscSectionGetConstraintDof(globalSection, p, &cdof);CHKERRQ(ierr); 3181 nleaves += dof < 0 ? -(dof+1)-cdof : dof-cdof; 3182 } 3183 ierr = PetscMalloc(nleaves * sizeof(PetscInt), &local);CHKERRQ(ierr); 3184 ierr = PetscMalloc(nleaves * sizeof(PetscSFNode), &remote);CHKERRQ(ierr); 3185 for(p = pStart, l = 0; p < pEnd; ++p) { 3186 PetscInt *cind; 3187 PetscInt dof, gdof, cdof, dim, off, goff, d, c; 3188 3189 ierr = PetscSectionGetDof(localSection, p, &dof);CHKERRQ(ierr); 3190 ierr = PetscSectionGetOffset(localSection, p, &off);CHKERRQ(ierr); 3191 ierr = PetscSectionGetConstraintDof(localSection, p, &cdof);CHKERRQ(ierr); 3192 ierr = PetscSectionGetConstraintIndices(localSection, p, &cind);CHKERRQ(ierr); 3193 ierr = PetscSectionGetDof(globalSection, p, &gdof);CHKERRQ(ierr); 3194 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 3195 dim = dof-cdof; 3196 for(d = 0, c = 0; d < dof; ++d) { 3197 if ((c < cdof) && (cind[c] == d)) {++c; continue;} 3198 local[l+d-c] = off+d; 3199 } 3200 if (gdof < 0) { 3201 for(d = 0; d < dim; ++d, ++l) { 3202 PetscInt offset = -(goff+1) + d, r; 3203 3204 for(r = 0; r < size; ++r) { 3205 if ((offset >= ranges[r]) && (offset < ranges[r+1])) break; 3206 } 3207 remote[l].rank = r; 3208 remote[l].index = offset - ranges[r]; 3209 } 3210 } else { 3211 for(d = 0; d < dim; ++d, ++l) { 3212 remote[l].rank = rank; 3213 remote[l].index = goff+d - ranges[rank]; 3214 } 3215 } 3216 } 3217 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3218 ierr = PetscSFSetGraph(dm->defaultSF, nroots, nleaves, local, PETSC_OWN_POINTER, remote, PETSC_OWN_POINTER);CHKERRQ(ierr); 3219 PetscFunctionReturn(0); 3220 } 3221 3222 #undef __FUNCT__ 3223 #define __FUNCT__ "DMGetNumFields" 3224 PetscErrorCode DMGetNumFields(DM dm, PetscInt *numFields) 3225 { 3226 PetscFunctionBegin; 3227 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3228 PetscValidPointer(numFields, 2); 3229 *numFields = dm->numFields; 3230 PetscFunctionReturn(0); 3231 } 3232 3233 #undef __FUNCT__ 3234 #define __FUNCT__ "DMSetNumFields" 3235 PetscErrorCode DMSetNumFields(DM dm, PetscInt numFields) 3236 { 3237 PetscInt f; 3238 PetscErrorCode ierr; 3239 3240 PetscFunctionBegin; 3241 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3242 for(f = 0; f < dm->numFields; ++f) { 3243 ierr = PetscObjectDestroy(&dm->fields[f]);CHKERRQ(ierr); 3244 } 3245 ierr = PetscFree(dm->fields);CHKERRQ(ierr); 3246 dm->numFields = numFields; 3247 ierr = PetscMalloc(dm->numFields * sizeof(PetscObject), &dm->fields);CHKERRQ(ierr); 3248 for(f = 0; f < dm->numFields; ++f) { 3249 ierr = PetscContainerCreate(((PetscObject) dm)->comm, (PetscContainer *) &dm->fields[f]);CHKERRQ(ierr); 3250 } 3251 PetscFunctionReturn(0); 3252 } 3253 3254 #undef __FUNCT__ 3255 #define __FUNCT__ "DMGetField" 3256 PetscErrorCode DMGetField(DM dm, PetscInt f, PetscObject *field) 3257 { 3258 PetscFunctionBegin; 3259 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3260 PetscValidPointer(field, 2); 3261 if (!dm->fields) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Fields have not been setup in this DM. Call DMSetNumFields()"); 3262 if ((f < 0) || (f >= dm->numFields)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Field %d should be in [%d,%d)", f, 0, dm->numFields); 3263 *field = dm->fields[f]; 3264 PetscFunctionReturn(0); 3265 } 3266