1 /* 2 Provides utility routines for manipulating any type of PETSc object. 3 */ 4 #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/ 5 #include <petscviewer.h> 6 7 #if defined(PETSC_USE_LOG) 8 PETSC_INTERN PetscObject *PetscObjects; 9 PETSC_INTERN PetscInt PetscObjectsCounts; 10 PETSC_INTERN PetscInt PetscObjectsMaxCounts; 11 PETSC_INTERN PetscBool PetscObjectsLog; 12 #endif 13 14 #if defined(PETSC_USE_LOG) 15 PetscObject *PetscObjects = NULL; 16 PetscInt PetscObjectsCounts = 0, PetscObjectsMaxCounts = 0; 17 PetscBool PetscObjectsLog = PETSC_FALSE; 18 #endif 19 20 PETSC_EXTERN PetscErrorCode PetscObjectGetComm_Petsc(PetscObject,MPI_Comm*); 21 PETSC_EXTERN PetscErrorCode PetscObjectCompose_Petsc(PetscObject,const char[],PetscObject); 22 PETSC_EXTERN PetscErrorCode PetscObjectQuery_Petsc(PetscObject,const char[],PetscObject*); 23 PETSC_EXTERN PetscErrorCode PetscObjectComposeFunction_Petsc(PetscObject,const char[],void (*)(void)); 24 PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Petsc(PetscObject,const char[],void (**)(void)); 25 26 /* 27 PetscHeaderCreate_Private - Creates a base PETSc object header and fills 28 in the default values. Called by the macro PetscHeaderCreate(). 29 */ 30 PetscErrorCode PetscHeaderCreate_Private(PetscObject h,PetscClassId classid,const char class_name[],const char descr[],const char mansec[], 31 MPI_Comm comm,PetscObjectDestroyFunction destroy,PetscObjectViewFunction view) 32 { 33 static PetscInt idcnt = 1; 34 #if defined(PETSC_USE_LOG) 35 PetscObject *newPetscObjects; 36 PetscInt newPetscObjectsMaxCounts,i; 37 #endif 38 39 PetscFunctionBegin; 40 h->classid = classid; 41 h->type = 0; 42 h->class_name = (char*)class_name; 43 h->description = (char*)descr; 44 h->mansec = (char*)mansec; 45 h->prefix = NULL; 46 h->refct = 1; 47 #if defined(PETSC_HAVE_SAWS) 48 h->amsmem = PETSC_FALSE; 49 #endif 50 h->id = idcnt++; 51 h->parentid = 0; 52 h->qlist = NULL; 53 h->olist = NULL; 54 h->bops->destroy = destroy; 55 h->bops->view = view; 56 h->bops->getcomm = PetscObjectGetComm_Petsc; 57 h->bops->compose = PetscObjectCompose_Petsc; 58 h->bops->query = PetscObjectQuery_Petsc; 59 h->bops->composefunction = PetscObjectComposeFunction_Petsc; 60 h->bops->queryfunction = PetscObjectQueryFunction_Petsc; 61 62 PetscCall(PetscCommDuplicate(comm,&h->comm,&h->tag)); 63 64 #if defined(PETSC_USE_LOG) 65 /* Keep a record of object created */ 66 if (PetscObjectsLog) { 67 PetscObjectsCounts++; 68 for (i=0; i<PetscObjectsMaxCounts; i++) { 69 if (!PetscObjects[i]) { 70 PetscObjects[i] = h; 71 PetscFunctionReturn(0); 72 } 73 } 74 /* Need to increase the space for storing PETSc objects */ 75 if (!PetscObjectsMaxCounts) newPetscObjectsMaxCounts = 100; 76 else newPetscObjectsMaxCounts = 2*PetscObjectsMaxCounts; 77 PetscCall(PetscCalloc1(newPetscObjectsMaxCounts,&newPetscObjects)); 78 PetscCall(PetscArraycpy(newPetscObjects,PetscObjects,PetscObjectsMaxCounts)); 79 PetscCall(PetscFree(PetscObjects)); 80 81 PetscObjects = newPetscObjects; 82 PetscObjects[PetscObjectsMaxCounts] = h; 83 PetscObjectsMaxCounts = newPetscObjectsMaxCounts; 84 } 85 #endif 86 PetscFunctionReturn(0); 87 } 88 89 PETSC_INTERN PetscBool PetscMemoryCollectMaximumUsage; 90 PETSC_INTERN PetscLogDouble PetscMemoryMaximumUsage; 91 92 /* 93 PetscHeaderDestroy_Private - Destroys a base PETSc object header. Called by 94 the macro PetscHeaderDestroy(). 95 */ 96 PetscErrorCode PetscHeaderDestroy_Private(PetscObject h) 97 { 98 PetscFunctionBegin; 99 PetscValidHeader(h,1); 100 PetscCall(PetscLogObjectDestroy(h)); 101 PetscCall(PetscComposedQuantitiesDestroy(h)); 102 if (PetscMemoryCollectMaximumUsage) { 103 PetscLogDouble usage; 104 PetscCall(PetscMemoryGetCurrentUsage(&usage)); 105 if (usage > PetscMemoryMaximumUsage) PetscMemoryMaximumUsage = usage; 106 } 107 /* first destroy things that could execute arbitrary code */ 108 if (h->python_destroy) { 109 void *python_context = h->python_context; 110 PetscErrorCode (*python_destroy)(void*) = h->python_destroy; 111 h->python_context = NULL; 112 h->python_destroy = NULL; 113 114 PetscCall((*python_destroy)(python_context)); 115 } 116 PetscCall(PetscObjectDestroyOptionsHandlers(h)); 117 PetscCall(PetscObjectListDestroy(&h->olist)); 118 PetscCall(PetscCommDestroy(&h->comm)); 119 /* next destroy other things */ 120 h->classid = PETSCFREEDHEADER; 121 122 if (PetscPrintFunctionList) PetscCall(PetscFunctionListPrintNonEmpty(h->qlist)); 123 PetscCall(PetscFunctionListDestroy(&h->qlist)); 124 PetscCall(PetscFree(h->type_name)); 125 PetscCall(PetscFree(h->name)); 126 PetscCall(PetscFree(h->prefix)); 127 PetscCall(PetscFree(h->fortran_func_pointers)); 128 PetscCall(PetscFree(h->fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS])); 129 PetscCall(PetscFree(h->fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE])); 130 131 #if defined(PETSC_USE_LOG) 132 if (PetscObjectsLog) { 133 PetscInt i; 134 /* Record object removal from list of all objects */ 135 for (i=0; i<PetscObjectsMaxCounts; i++) { 136 if (PetscObjects[i] == h) { 137 PetscObjects[i] = NULL; 138 PetscObjectsCounts--; 139 break; 140 } 141 } 142 if (!PetscObjectsCounts) { 143 PetscCall(PetscFree(PetscObjects)); 144 PetscObjectsMaxCounts = 0; 145 } 146 } 147 #endif 148 PetscFunctionReturn(0); 149 } 150 151 /*@C 152 PetscObjectCopyFortranFunctionPointers - Copy function pointers to another object 153 154 Logically Collective on PetscObject 155 156 Input Parameters: 157 + src - source object 158 - dest - destination object 159 160 Level: developer 161 162 Note: 163 Both objects must have the same class. 164 @*/ 165 PetscErrorCode PetscObjectCopyFortranFunctionPointers(PetscObject src,PetscObject dest) 166 { 167 PetscFortranCallbackId cbtype,numcb[PETSC_FORTRAN_CALLBACK_MAXTYPE]; 168 169 PetscFunctionBegin; 170 PetscValidHeader(src,1); 171 PetscValidHeader(dest,2); 172 PetscCheck(src->classid == dest->classid,src->comm,PETSC_ERR_ARG_INCOMP,"Objects must be of the same class"); 173 174 PetscCall(PetscFree(dest->fortran_func_pointers)); 175 PetscCall(PetscMalloc(src->num_fortran_func_pointers*sizeof(void(*)(void)),&dest->fortran_func_pointers)); 176 PetscCall(PetscMemcpy(dest->fortran_func_pointers,src->fortran_func_pointers,src->num_fortran_func_pointers*sizeof(void(*)(void)))); 177 178 dest->num_fortran_func_pointers = src->num_fortran_func_pointers; 179 180 PetscCall(PetscFortranCallbackGetSizes(src->classid,&numcb[PETSC_FORTRAN_CALLBACK_CLASS],&numcb[PETSC_FORTRAN_CALLBACK_SUBTYPE])); 181 for (cbtype=PETSC_FORTRAN_CALLBACK_CLASS; cbtype<PETSC_FORTRAN_CALLBACK_MAXTYPE; cbtype++) { 182 PetscCall(PetscFree(dest->fortrancallback[cbtype])); 183 PetscCall(PetscCalloc1(numcb[cbtype],&dest->fortrancallback[cbtype])); 184 PetscCall(PetscMemcpy(dest->fortrancallback[cbtype],src->fortrancallback[cbtype],src->num_fortrancallback[cbtype]*sizeof(PetscFortranCallback))); 185 dest->num_fortrancallback[cbtype] = src->num_fortrancallback[cbtype]; 186 } 187 PetscFunctionReturn(0); 188 } 189 190 /*@C 191 PetscObjectSetFortranCallback - set fortran callback function pointer and context 192 193 Logically Collective 194 195 Input Parameters: 196 + obj - object on which to set callback 197 . cbtype - callback type (class or subtype) 198 . cid - address of callback Id, updated if not yet initialized (zero) 199 . func - Fortran function 200 - ctx - Fortran context 201 202 Level: developer 203 204 .seealso: `PetscObjectGetFortranCallback()` 205 @*/ 206 PetscErrorCode PetscObjectSetFortranCallback(PetscObject obj,PetscFortranCallbackType cbtype,PetscFortranCallbackId *cid,void (*func)(void),void *ctx) 207 { 208 const char *subtype = NULL; 209 210 PetscFunctionBegin; 211 PetscValidHeader(obj,1); 212 if (cbtype == PETSC_FORTRAN_CALLBACK_SUBTYPE) subtype = obj->type_name; 213 if (!*cid) PetscCall(PetscFortranCallbackRegister(obj->classid,subtype,cid)); 214 if (*cid >= PETSC_SMALLEST_FORTRAN_CALLBACK+obj->num_fortrancallback[cbtype]) { 215 PetscFortranCallbackId oldnum = obj->num_fortrancallback[cbtype]; 216 PetscFortranCallbackId newnum = PetscMax(*cid - PETSC_SMALLEST_FORTRAN_CALLBACK + 1, 2*oldnum); 217 PetscFortranCallback *callback; 218 PetscCall(PetscMalloc1(newnum,&callback)); 219 PetscCall(PetscMemcpy(callback,obj->fortrancallback[cbtype],oldnum*sizeof(*obj->fortrancallback[cbtype]))); 220 PetscCall(PetscFree(obj->fortrancallback[cbtype])); 221 222 obj->fortrancallback[cbtype] = callback; 223 obj->num_fortrancallback[cbtype] = newnum; 224 } 225 obj->fortrancallback[cbtype][*cid-PETSC_SMALLEST_FORTRAN_CALLBACK].func = func; 226 obj->fortrancallback[cbtype][*cid-PETSC_SMALLEST_FORTRAN_CALLBACK].ctx = ctx; 227 PetscFunctionReturn(0); 228 } 229 230 /*@C 231 PetscObjectGetFortranCallback - get fortran callback function pointer and context 232 233 Logically Collective 234 235 Input Parameters: 236 + obj - object on which to get callback 237 . cbtype - callback type 238 - cid - address of callback Id 239 240 Output Parameters: 241 + func - Fortran function (or NULL if not needed) 242 - ctx - Fortran context (or NULL if not needed) 243 244 Level: developer 245 246 .seealso: `PetscObjectSetFortranCallback()` 247 @*/ 248 PetscErrorCode PetscObjectGetFortranCallback(PetscObject obj,PetscFortranCallbackType cbtype,PetscFortranCallbackId cid,void (**func)(void),void **ctx) 249 { 250 PetscFortranCallback *cb; 251 252 PetscFunctionBegin; 253 PetscValidHeader(obj,1); 254 PetscCheck(cid >= PETSC_SMALLEST_FORTRAN_CALLBACK,obj->comm,PETSC_ERR_ARG_CORRUPT,"Fortran callback Id invalid"); 255 PetscCheck(cid < PETSC_SMALLEST_FORTRAN_CALLBACK+obj->num_fortrancallback[cbtype],obj->comm,PETSC_ERR_ARG_CORRUPT,"Fortran callback not set on this object"); 256 cb = &obj->fortrancallback[cbtype][cid-PETSC_SMALLEST_FORTRAN_CALLBACK]; 257 if (func) *func = cb->func; 258 if (ctx) *ctx = cb->ctx; 259 PetscFunctionReturn(0); 260 } 261 262 #if defined(PETSC_USE_LOG) 263 /*@C 264 PetscObjectsDump - Prints the currently existing objects. 265 266 Logically Collective on PetscViewer 267 268 Input Parameters: 269 + fd - file pointer 270 - all - by default only tries to display objects created explicitly by the user, if all is PETSC_TRUE then lists all outstanding objects 271 272 Options Database: 273 . -objects_dump <all> - print information about all the objects that exist at the end of the programs run 274 275 Level: advanced 276 277 @*/ 278 PetscErrorCode PetscObjectsDump(FILE *fd,PetscBool all) 279 { 280 PetscInt i; 281 #if defined(PETSC_USE_DEBUG) 282 PetscInt j,k=0; 283 #endif 284 PetscObject h; 285 286 PetscFunctionBegin; 287 if (PetscObjectsCounts) { 288 PetscCall(PetscFPrintf(PETSC_COMM_WORLD,fd,"The following objects were never freed\n")); 289 PetscCall(PetscFPrintf(PETSC_COMM_WORLD,fd,"-----------------------------------------\n")); 290 for (i=0; i<PetscObjectsMaxCounts; i++) { 291 if ((h = PetscObjects[i])) { 292 PetscCall(PetscObjectName(h)); 293 { 294 #if defined(PETSC_USE_DEBUG) 295 PetscStack *stack = NULL; 296 char *create,*rclass; 297 298 /* if the PETSc function the user calls is not a create then this object was NOT directly created by them */ 299 PetscCall(PetscMallocGetStack(h,&stack)); 300 if (stack) { 301 k = stack->currentsize-2; 302 if (!all) { 303 k = 0; 304 while (!stack->petscroutine[k]) k++; 305 PetscCall(PetscStrstr(stack->function[k],"Create",&create)); 306 if (!create) { 307 PetscCall(PetscStrstr(stack->function[k],"Get",&create)); 308 } 309 PetscCall(PetscStrstr(stack->function[k],h->class_name,&rclass)); 310 if (!create) continue; 311 if (!rclass) continue; 312 } 313 } 314 #endif 315 316 PetscCall(PetscFPrintf(PETSC_COMM_WORLD,fd,"[%d] %s %s %s\n",PetscGlobalRank,h->class_name,h->type_name,h->name)); 317 318 #if defined(PETSC_USE_DEBUG) 319 PetscCall(PetscMallocGetStack(h,&stack)); 320 if (stack) { 321 for (j=k; j>=0; j--) { 322 fprintf(fd," [%d] %s() in %s\n",PetscGlobalRank,stack->function[j],stack->file[j]); 323 } 324 } 325 #endif 326 } 327 } 328 } 329 } 330 PetscFunctionReturn(0); 331 } 332 #endif 333 334 #if defined(PETSC_USE_LOG) 335 336 /*@C 337 PetscObjectsView - Prints the currently existing objects. 338 339 Logically Collective on PetscViewer 340 341 Input Parameter: 342 . viewer - must be an PETSCVIEWERASCII viewer 343 344 Level: advanced 345 346 @*/ 347 PetscErrorCode PetscObjectsView(PetscViewer viewer) 348 { 349 PetscBool isascii; 350 FILE *fd; 351 352 PetscFunctionBegin; 353 if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD; 354 PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii)); 355 PetscCheck(isascii,PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Only supports ASCII viewer"); 356 PetscCall(PetscViewerASCIIGetPointer(viewer,&fd)); 357 PetscCall(PetscObjectsDump(fd,PETSC_TRUE)); 358 PetscFunctionReturn(0); 359 } 360 361 /*@C 362 PetscObjectsGetObject - Get a pointer to a named object 363 364 Not collective 365 366 Input Parameter: 367 . name - the name of an object 368 369 Output Parameters: 370 + obj - the object or null if there is no object 371 - classname - the name of the class 372 373 Level: advanced 374 375 @*/ 376 PetscErrorCode PetscObjectsGetObject(const char *name,PetscObject *obj,char **classname) 377 { 378 PetscInt i; 379 PetscObject h; 380 PetscBool flg; 381 382 PetscFunctionBegin; 383 PetscValidCharPointer(name,1); 384 PetscValidPointer(obj,2); 385 *obj = NULL; 386 for (i=0; i<PetscObjectsMaxCounts; i++) { 387 if ((h = PetscObjects[i])) { 388 PetscCall(PetscObjectName(h)); 389 PetscCall(PetscStrcmp(h->name,name,&flg)); 390 if (flg) { 391 *obj = h; 392 if (classname) *classname = h->class_name; 393 PetscFunctionReturn(0); 394 } 395 } 396 } 397 PetscFunctionReturn(0); 398 } 399 #endif 400 401 /*@ 402 PetscObjectSetPrintedOptions - indicate to an object that it should behave as if it has already printed the help for its options 403 404 Input Parameters: 405 . obj - the PetscObject 406 407 Level: developer 408 409 Developer Notes: 410 This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by 411 `PCBJACOBI` from all printing the same help messages to the screen 412 413 .seealso: `PetscOptionsInsert()` 414 @*/ 415 PetscErrorCode PetscObjectSetPrintedOptions(PetscObject obj) 416 { 417 PetscFunctionBegin; 418 PetscValidPointer(obj,1); 419 obj->optionsprinted = PETSC_TRUE; 420 PetscFunctionReturn(0); 421 } 422 423 /*@ 424 PetscObjectInheritPrintedOptions - If the child object is not on the rank 0 process of the parent object and the child is sequential then the child gets it set. 425 426 Input Parameters: 427 + pobj - the parent object 428 - obj - the PetscObject 429 430 Level: developer 431 432 Developer Notes: 433 This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by 434 `PCBJACOBI` from all printing the same help messages to the screen 435 436 This will not handle more complicated situations like with `PCGASM` where children may live on any subset of the parent's processes and overlap 437 438 .seealso: `PetscOptionsInsert()`, `PetscObjectSetPrintedOptions()` 439 @*/ 440 PetscErrorCode PetscObjectInheritPrintedOptions(PetscObject pobj,PetscObject obj) 441 { 442 PetscMPIInt prank,size; 443 444 PetscFunctionBegin; 445 PetscValidHeader(pobj,1); 446 PetscValidHeader(obj,2); 447 PetscCallMPI(MPI_Comm_rank(pobj->comm,&prank)); 448 PetscCallMPI(MPI_Comm_size(obj->comm,&size)); 449 if (size == 1 && prank > 0) obj->optionsprinted = PETSC_TRUE; 450 PetscFunctionReturn(0); 451 } 452 453 /*@C 454 PetscObjectAddOptionsHandler - Adds an additional function to check for options when XXXSetFromOptions() is called. 455 456 Not Collective 457 458 Input Parameters: 459 + obj - the PETSc object 460 . handle - function that checks for options 461 . destroy - function to destroy context if provided 462 - ctx - optional context for check function 463 464 Level: developer 465 466 .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectProcessOptionsHandlers()`, `PetscObjectDestroyOptionsHandlers()` 467 468 @*/ 469 PetscErrorCode PetscObjectAddOptionsHandler(PetscObject obj,PetscErrorCode (*handle)(PetscOptionItems*,PetscObject,void*),PetscErrorCode (*destroy)(PetscObject,void*),void *ctx) 470 { 471 PetscFunctionBegin; 472 PetscValidHeader(obj,1); 473 PetscCheck(obj->noptionhandler < PETSC_MAX_OPTIONS_HANDLER,obj->comm,PETSC_ERR_ARG_OUTOFRANGE,"To many options handlers added"); 474 obj->optionhandler[obj->noptionhandler] = handle; 475 obj->optiondestroy[obj->noptionhandler] = destroy; 476 obj->optionctx[obj->noptionhandler++] = ctx; 477 PetscFunctionReturn(0); 478 } 479 480 /*@C 481 PetscObjectProcessOptionsHandlers - Calls all the options handlers attached to an object 482 483 Not Collective 484 485 Input Parameter: 486 . obj - the PETSc object 487 488 Level: developer 489 490 .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectDestroyOptionsHandlers()` 491 492 @*/ 493 PetscErrorCode PetscObjectProcessOptionsHandlers(PetscOptionItems *PetscOptionsObject,PetscObject obj) 494 { 495 PetscFunctionBegin; 496 PetscValidHeader(obj,2); 497 for (PetscInt i=0; i<obj->noptionhandler; i++) PetscCall((*obj->optionhandler[i])(PetscOptionsObject,obj,obj->optionctx[i])); 498 PetscFunctionReturn(0); 499 } 500 501 /*@C 502 PetscObjectDestroyOptionsHandlers - Destroys all the option handlers attached to an object 503 504 Not Collective 505 506 Input Parameter: 507 . obj - the PETSc object 508 509 Level: developer 510 511 .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectProcessOptionsHandlers()` 512 513 @*/ 514 PetscErrorCode PetscObjectDestroyOptionsHandlers(PetscObject obj) 515 { 516 PetscFunctionBegin; 517 PetscValidHeader(obj,1); 518 for (PetscInt i=0; i<obj->noptionhandler; i++) { 519 if (obj->optiondestroy[i]) PetscCall((*obj->optiondestroy[i])(obj,obj->optionctx[i])); 520 } 521 obj->noptionhandler = 0; 522 PetscFunctionReturn(0); 523 } 524 525 /*@C 526 PetscObjectReference - Indicates to any `PetscObject` that it is being 527 referenced by another `PetscObject`. This increases the reference 528 count for that object by one. 529 530 Logically Collective on `PetscObject` 531 532 Input Parameter: 533 . obj - the PETSc object. This must be cast with (PetscObject), for example, 534 PetscObjectReference((PetscObject)mat); 535 536 Level: advanced 537 538 .seealso: `PetscObjectCompose()`, `PetscObjectDereference()` 539 @*/ 540 PetscErrorCode PetscObjectReference(PetscObject obj) 541 { 542 PetscFunctionBegin; 543 if (!obj) PetscFunctionReturn(0); 544 PetscValidHeader(obj,1); 545 obj->refct++; 546 PetscFunctionReturn(0); 547 } 548 549 /*@C 550 PetscObjectGetReference - Gets the current reference count for 551 any PETSc object. 552 553 Not Collective 554 555 Input Parameter: 556 . obj - the PETSc object; this must be cast with (PetscObject), for example, 557 PetscObjectGetReference((PetscObject)mat,&cnt); 558 559 Output Parameter: 560 . cnt - the reference count 561 562 Level: advanced 563 564 .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObjectReference()` 565 @*/ 566 PetscErrorCode PetscObjectGetReference(PetscObject obj,PetscInt *cnt) 567 { 568 PetscFunctionBegin; 569 PetscValidHeader(obj,1); 570 PetscValidIntPointer(cnt,2); 571 *cnt = obj->refct; 572 PetscFunctionReturn(0); 573 } 574 575 /*@C 576 PetscObjectDereference - Indicates to any `PetscObject` that it is being 577 referenced by one less `PetscObject`. This decreases the reference 578 count for that object by one. 579 580 Collective on `PetscObject` if reference reaches 0 otherwise Logically Collective 581 582 Input Parameter: 583 . obj - the PETSc object; this must be cast with (PetscObject), for example, 584 PetscObjectDereference((PetscObject)mat); 585 586 Notes: 587 `PetscObjectDestroy()` sets the obj pointer to null after the call, this routine does not. 588 589 Level: advanced 590 591 .seealso: `PetscObjectCompose()`, `PetscObjectReference()`, `PetscObjectDestroy()` 592 @*/ 593 PetscErrorCode PetscObjectDereference(PetscObject obj) 594 { 595 PetscFunctionBegin; 596 if (!obj) PetscFunctionReturn(0); 597 PetscValidHeader(obj,1); 598 if (obj->bops->destroy) PetscCall((*obj->bops->destroy)(&obj)); 599 else PetscCheck(--(obj->refct),PETSC_COMM_SELF,PETSC_ERR_SUP,"This PETSc object does not have a generic destroy routine"); 600 PetscFunctionReturn(0); 601 } 602 603 /* ----------------------------------------------------------------------- */ 604 /* 605 The following routines are the versions private to the PETSc object 606 data structures. 607 */ 608 PetscErrorCode PetscObjectGetComm_Petsc(PetscObject obj,MPI_Comm *comm) 609 { 610 PetscFunctionBegin; 611 PetscValidHeader(obj,1); 612 PetscValidPointer(comm,2); 613 *comm = obj->comm; 614 PetscFunctionReturn(0); 615 } 616 617 PetscErrorCode PetscObjectRemoveReference(PetscObject obj,const char name[]) 618 { 619 PetscFunctionBegin; 620 PetscValidHeader(obj,1); 621 PetscCall(PetscObjectListRemoveReference(&obj->olist,name)); 622 PetscFunctionReturn(0); 623 } 624 625 PetscErrorCode PetscObjectCompose_Petsc(PetscObject obj,const char name[],PetscObject ptr) 626 { 627 PetscFunctionBegin; 628 if (ptr) { 629 char *tname; 630 PetscBool skipreference; 631 632 PetscCall(PetscObjectListReverseFind(ptr->olist,obj,&tname,&skipreference)); 633 if (tname) PetscCheck(skipreference,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"An object cannot be composed with an object that was composed with it"); 634 } 635 PetscCall(PetscObjectListAdd(&obj->olist,name,ptr)); 636 PetscFunctionReturn(0); 637 } 638 639 PetscErrorCode PetscObjectQuery_Petsc(PetscObject obj,const char name[],PetscObject *ptr) 640 { 641 PetscFunctionBegin; 642 PetscValidHeader(obj,1); 643 PetscCall(PetscObjectListFind(obj->olist,name,ptr)); 644 PetscFunctionReturn(0); 645 } 646 647 PetscErrorCode PetscObjectComposeFunction_Petsc(PetscObject obj,const char name[],void (*ptr)(void)) 648 { 649 PetscFunctionBegin; 650 PetscValidHeader(obj,1); 651 PetscCall(PetscFunctionListAdd(&obj->qlist,name,ptr)); 652 PetscFunctionReturn(0); 653 } 654 655 PetscErrorCode PetscObjectQueryFunction_Petsc(PetscObject obj,const char name[],void (**ptr)(void)) 656 { 657 PetscFunctionBegin; 658 PetscValidHeader(obj,1); 659 PetscCall(PetscFunctionListFind(obj->qlist,name,ptr)); 660 PetscFunctionReturn(0); 661 } 662 663 /*@C 664 PetscObjectCompose - Associates another PETSc object with a given PETSc object. 665 666 Not Collective 667 668 Input Parameters: 669 + obj - the PETSc object; this must be cast with (PetscObject), for example, 670 PetscObjectCompose((PetscObject)mat,...); 671 . name - name associated with the child object 672 - ptr - the other PETSc object to associate with the PETSc object; this must also be 673 cast with (PetscObject) 674 675 Level: advanced 676 677 Notes: 678 The second objects reference count is automatically increased by one when it is 679 composed. 680 681 Replaces any previous object that had the same name. 682 683 If ptr is null and name has previously been composed using an object, then that 684 entry is removed from the obj. 685 686 `PetscObjectCompose()` can be used with any PETSc object (such as 687 `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object. 688 689 `PetscContainerCreate()` can be used to create an object from a 690 user-provided pointer that may then be composed with PETSc objects using `PetscObjectCompose()` 691 692 .seealso: `PetscObjectQuery()`, `PetscContainerCreate()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`, 693 `PetscContainerSetPointer()` 694 @*/ 695 PetscErrorCode PetscObjectCompose(PetscObject obj,const char name[],PetscObject ptr) 696 { 697 PetscFunctionBegin; 698 PetscValidHeader(obj,1); 699 PetscValidCharPointer(name,2); 700 if (ptr) PetscValidHeader(ptr,3); 701 PetscCheck(obj != ptr,PetscObjectComm((PetscObject)obj),PETSC_ERR_SUP,"Cannot compose object with itself"); 702 PetscCall((*obj->bops->compose)(obj,name,ptr)); 703 PetscFunctionReturn(0); 704 } 705 706 /*@C 707 PetscObjectQuery - Gets a PETSc object associated with a given object that was composed with `PetscObjectCompose()` 708 709 Not Collective 710 711 Input Parameters: 712 + obj - the PETSc object 713 Thus must be cast with a (PetscObject), for example, 714 PetscObjectCompose((PetscObject)mat,...); 715 . name - name associated with child object 716 - ptr - the other PETSc object associated with the PETSc object, this must be 717 cast with (PetscObject*) 718 719 Level: advanced 720 721 Note: 722 The reference count of neither object is increased in this call 723 724 .seealso: `PetscObjectCompose()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer` 725 `PetscContainerGetPointer()` 726 @*/ 727 PetscErrorCode PetscObjectQuery(PetscObject obj,const char name[],PetscObject *ptr) 728 { 729 PetscFunctionBegin; 730 PetscValidHeader(obj,1); 731 PetscValidCharPointer(name,2); 732 PetscValidPointer(ptr,3); 733 PetscCall((*obj->bops->query)(obj,name,ptr)); 734 PetscFunctionReturn(0); 735 } 736 737 /*MC 738 PetscObjectComposeFunction - Associates a function with a given PETSc object. 739 740 Synopsis: 741 #include <petscsys.h> 742 PetscErrorCode PetscObjectComposeFunction(PetscObject obj,const char name[],void (*fptr)(void)) 743 744 Logically Collective on PetscObject 745 746 Input Parameters: 747 + obj - the PETSc object; this must be cast with a (PetscObject), for example, 748 PetscObjectCompose((PetscObject)mat,...); 749 . name - name associated with the child function 750 . fname - name of the function 751 - fptr - function pointer 752 753 Level: advanced 754 755 Notes: 756 To remove a registered routine, pass in NULL for fptr(). 757 758 PetscObjectComposeFunction() can be used with any PETSc object (such as 759 `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object. 760 761 .seealso: `PetscObjectQueryFunction()`, `PetscContainerCreate()` `PetscObjectCompose()`, `PetscObjectQuery()` 762 M*/ 763 764 PetscErrorCode PetscObjectComposeFunction_Private(PetscObject obj,const char name[],void (*fptr)(void)) 765 { 766 PetscFunctionBegin; 767 PetscValidHeader(obj,1); 768 PetscValidCharPointer(name,2); 769 PetscCall((*obj->bops->composefunction)(obj,name,fptr)); 770 PetscFunctionReturn(0); 771 } 772 773 /*MC 774 PetscObjectQueryFunction - Gets a function associated with a given object. 775 776 Synopsis: 777 #include <petscsys.h> 778 PetscErrorCode PetscObjectQueryFunction(PetscObject obj,const char name[],void (**fptr)(void)) 779 780 Logically Collective on PetscObject 781 782 Input Parameters: 783 + obj - the PETSc object; this must be cast with (PetscObject), for example, 784 PetscObjectQueryFunction((PetscObject)ksp,...); 785 - name - name associated with the child function 786 787 Output Parameter: 788 . fptr - function pointer 789 790 Level: advanced 791 792 .seealso: `PetscObjectComposeFunction()`, `PetscFunctionListFind()`, `PetscObjectCompose()`, `PetscObjectQuery()` 793 M*/ 794 PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj,const char name[],void (**ptr)(void)) 795 { 796 PetscFunctionBegin; 797 PetscValidHeader(obj,1); 798 PetscValidCharPointer(name,2); 799 PetscCall((*obj->bops->queryfunction)(obj,name,ptr)); 800 PetscFunctionReturn(0); 801 } 802 803 struct _p_PetscContainer { 804 PETSCHEADER(int); 805 void *ptr; 806 PetscErrorCode (*userdestroy)(void*); 807 }; 808 809 /*@C 810 PetscContainerUserDestroyDefault - Default destroy routine for user-provided data that simply calls `PetscFree()` in the data 811 provided with `PetscContainerSetPointer()` 812 813 Logically Collective on `PetscContainer` 814 815 Input Parameter: 816 . ctx - pointer to user-provided data 817 818 Level: advanced 819 820 .seealso: `PetscContainerDestroy()`, `PetscContainerSetUserDestroy()` 821 @*/ 822 PetscErrorCode PetscContainerUserDestroyDefault(void* ctx) 823 { 824 PetscFunctionBegin; 825 PetscCall(PetscFree(ctx)); 826 PetscFunctionReturn(0); 827 } 828 829 /*@C 830 PetscContainerGetPointer - Gets the pointer value contained in the container that was provided with `PetscContainerSetPointer()` 831 832 Not Collective 833 834 Input Parameter: 835 . obj - the object created with `PetscContainerCreate()` 836 837 Output Parameter: 838 . ptr - the pointer value 839 840 Level: advanced 841 842 .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, 843 `PetscContainerSetPointer()` 844 @*/ 845 PetscErrorCode PetscContainerGetPointer(PetscContainer obj,void **ptr) 846 { 847 PetscFunctionBegin; 848 PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1); 849 PetscValidPointer(ptr,2); 850 *ptr = obj->ptr; 851 PetscFunctionReturn(0); 852 } 853 854 /*@C 855 PetscContainerSetPointer - Sets the pointer value contained in the container. 856 857 Logically Collective on `PetscContainer` 858 859 Input Parameters: 860 + obj - the object created with `PetscContainerCreate()` 861 - ptr - the pointer value 862 863 Level: advanced 864 865 .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObjectCompose()`, `PetscObjectQuery()`, 866 `PetscContainerGetPointer()` 867 @*/ 868 PetscErrorCode PetscContainerSetPointer(PetscContainer obj,void *ptr) 869 { 870 PetscFunctionBegin; 871 PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1); 872 if (ptr) PetscValidPointer(ptr,2); 873 obj->ptr = ptr; 874 PetscFunctionReturn(0); 875 } 876 877 /*@C 878 PetscContainerDestroy - Destroys a PETSc container object. 879 880 Collective on `PetscContainer` 881 882 Input Parameter: 883 . obj - an object that was created with `PetscContainerCreate()` 884 885 Level: advanced 886 887 Notes: 888 If `PetscContainerSetUserDestroy()` was used to provide a user destroy object for the data provided with `PetscContainerSetPointer()` 889 then that function is called to destroy the data. 890 891 .seealso: `PetscContainerCreate()`, `PetscContainerSetUserDestroy()` 892 @*/ 893 PetscErrorCode PetscContainerDestroy(PetscContainer *obj) 894 { 895 PetscFunctionBegin; 896 if (!*obj) PetscFunctionReturn(0); 897 PetscValidHeaderSpecific(*obj,PETSC_CONTAINER_CLASSID,1); 898 if (--((PetscObject)(*obj))->refct > 0) {*obj = NULL; PetscFunctionReturn(0);} 899 if ((*obj)->userdestroy) PetscCall((*(*obj)->userdestroy)((*obj)->ptr)); 900 PetscCall(PetscHeaderDestroy(obj)); 901 PetscFunctionReturn(0); 902 } 903 904 /*@C 905 PetscContainerSetUserDestroy - Sets name of the user destroy function for the data provided to the `PetscContainer` with `PetscContainerSetPointer()` 906 907 Logically Collective on `PetscContainer` 908 909 Input Parameters: 910 + obj - an object that was created with `PetscContainerCreate()` 911 - des - name of the user destroy function 912 913 Notes: 914 Use `PetscContainerUserDestroyDefault()` if the memory was obtained by calling `PetscMalloc()` or one of its variants for single memory allocation. 915 916 Level: advanced 917 918 .seealso: `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()` 919 @*/ 920 PetscErrorCode PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void*)) 921 { 922 PetscFunctionBegin; 923 PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1); 924 obj->userdestroy = des; 925 PetscFunctionReturn(0); 926 } 927 928 PetscClassId PETSC_CONTAINER_CLASSID; 929 930 /*@C 931 PetscContainerCreate - Creates a PETSc object that has room to hold 932 a single pointer. This allows one to attach any type of data (accessible 933 through a pointer) with the `PetscObjectCompose()` function to a `PetscObject`. 934 The data item itself is attached by a call to `PetscContainerSetPointer()`. 935 936 Collective 937 938 Input Parameters: 939 . comm - MPI communicator that shares the object 940 941 Output Parameters: 942 . container - the container created 943 944 Level: advanced 945 946 .seealso: `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`, 947 `PetscContainerSetUserDestroy()` 948 @*/ 949 PetscErrorCode PetscContainerCreate(MPI_Comm comm,PetscContainer *container) 950 { 951 PetscFunctionBegin; 952 PetscValidPointer(container,2); 953 PetscCall(PetscSysInitializePackage()); 954 PetscCall(PetscHeaderCreate(*container,PETSC_CONTAINER_CLASSID,"PetscContainer","Container","Sys",comm,PetscContainerDestroy,NULL)); 955 PetscFunctionReturn(0); 956 } 957 958 /*@ 959 PetscObjectSetFromOptions - Sets generic parameters from user options. 960 961 Collective on obj 962 963 Input Parameter: 964 . obj - the `PetscObject` 965 966 Options Database Keys: 967 968 Notes: 969 We have no generic options at present, so this does nothing 970 971 Level: beginner 972 973 .seealso: `PetscObjectSetOptionsPrefix()`, `PetscObjectGetOptionsPrefix()` 974 @*/ 975 PetscErrorCode PetscObjectSetFromOptions(PetscObject obj) 976 { 977 PetscFunctionBegin; 978 PetscValidHeader(obj,1); 979 PetscFunctionReturn(0); 980 } 981 982 /*@ 983 PetscObjectSetUp - Sets up the internal data structures for the later use. 984 985 Collective on `PetscObject` 986 987 Input Parameters: 988 . obj - the `PetscObject` 989 990 Notes: 991 This does nothing at present. 992 993 Level: advanced 994 995 .seealso: `PetscObjectDestroy()` 996 @*/ 997 PetscErrorCode PetscObjectSetUp(PetscObject obj) 998 { 999 PetscFunctionBegin; 1000 PetscValidHeader(obj,1); 1001 PetscFunctionReturn(0); 1002 } 1003