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)(PetscObject,PetscOptionItems*,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 Parameters: 486 + obj - the PETSc object 487 - PetscOptionsObject - the options context 488 489 Level: developer 490 491 .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectDestroyOptionsHandlers()` 492 493 @*/ 494 PetscErrorCode PetscObjectProcessOptionsHandlers(PetscObject obj,PetscOptionItems *PetscOptionsObject) 495 { 496 PetscFunctionBegin; 497 PetscValidHeader(obj,1); 498 for (PetscInt i=0; i<obj->noptionhandler; i++) PetscCall((*obj->optionhandler[i])(obj,PetscOptionsObject,obj->optionctx[i])); 499 PetscFunctionReturn(0); 500 } 501 502 /*@C 503 PetscObjectDestroyOptionsHandlers - Destroys all the option handlers attached to an object 504 505 Not Collective 506 507 Input Parameter: 508 . obj - the PETSc object 509 510 Level: developer 511 512 .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectProcessOptionsHandlers()` 513 514 @*/ 515 PetscErrorCode PetscObjectDestroyOptionsHandlers(PetscObject obj) 516 { 517 PetscFunctionBegin; 518 PetscValidHeader(obj,1); 519 for (PetscInt i=0; i<obj->noptionhandler; i++) { 520 if (obj->optiondestroy[i]) PetscCall((*obj->optiondestroy[i])(obj,obj->optionctx[i])); 521 } 522 obj->noptionhandler = 0; 523 PetscFunctionReturn(0); 524 } 525 526 /*@C 527 PetscObjectReference - Indicates to any `PetscObject` that it is being 528 referenced by another `PetscObject`. This increases the reference 529 count for that object by one. 530 531 Logically Collective on `PetscObject` 532 533 Input Parameter: 534 . obj - the PETSc object. This must be cast with (PetscObject), for example, 535 PetscObjectReference((PetscObject)mat); 536 537 Level: advanced 538 539 .seealso: `PetscObjectCompose()`, `PetscObjectDereference()` 540 @*/ 541 PetscErrorCode PetscObjectReference(PetscObject obj) 542 { 543 PetscFunctionBegin; 544 if (!obj) PetscFunctionReturn(0); 545 PetscValidHeader(obj,1); 546 obj->refct++; 547 PetscFunctionReturn(0); 548 } 549 550 /*@C 551 PetscObjectGetReference - Gets the current reference count for 552 any PETSc object. 553 554 Not Collective 555 556 Input Parameter: 557 . obj - the PETSc object; this must be cast with (PetscObject), for example, 558 PetscObjectGetReference((PetscObject)mat,&cnt); 559 560 Output Parameter: 561 . cnt - the reference count 562 563 Level: advanced 564 565 .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObjectReference()` 566 @*/ 567 PetscErrorCode PetscObjectGetReference(PetscObject obj,PetscInt *cnt) 568 { 569 PetscFunctionBegin; 570 PetscValidHeader(obj,1); 571 PetscValidIntPointer(cnt,2); 572 *cnt = obj->refct; 573 PetscFunctionReturn(0); 574 } 575 576 /*@C 577 PetscObjectDereference - Indicates to any `PetscObject` that it is being 578 referenced by one less `PetscObject`. This decreases the reference 579 count for that object by one. 580 581 Collective on `PetscObject` if reference reaches 0 otherwise Logically Collective 582 583 Input Parameter: 584 . obj - the PETSc object; this must be cast with (PetscObject), for example, 585 PetscObjectDereference((PetscObject)mat); 586 587 Notes: 588 `PetscObjectDestroy()` sets the obj pointer to null after the call, this routine does not. 589 590 Level: advanced 591 592 .seealso: `PetscObjectCompose()`, `PetscObjectReference()`, `PetscObjectDestroy()` 593 @*/ 594 PetscErrorCode PetscObjectDereference(PetscObject obj) 595 { 596 PetscFunctionBegin; 597 if (!obj) PetscFunctionReturn(0); 598 PetscValidHeader(obj,1); 599 if (obj->bops->destroy) PetscCall((*obj->bops->destroy)(&obj)); 600 else PetscCheck(--(obj->refct),PETSC_COMM_SELF,PETSC_ERR_SUP,"This PETSc object does not have a generic destroy routine"); 601 PetscFunctionReturn(0); 602 } 603 604 /* ----------------------------------------------------------------------- */ 605 /* 606 The following routines are the versions private to the PETSc object 607 data structures. 608 */ 609 PetscErrorCode PetscObjectGetComm_Petsc(PetscObject obj,MPI_Comm *comm) 610 { 611 PetscFunctionBegin; 612 PetscValidHeader(obj,1); 613 PetscValidPointer(comm,2); 614 *comm = obj->comm; 615 PetscFunctionReturn(0); 616 } 617 618 PetscErrorCode PetscObjectRemoveReference(PetscObject obj,const char name[]) 619 { 620 PetscFunctionBegin; 621 PetscValidHeader(obj,1); 622 PetscCall(PetscObjectListRemoveReference(&obj->olist,name)); 623 PetscFunctionReturn(0); 624 } 625 626 PetscErrorCode PetscObjectCompose_Petsc(PetscObject obj,const char name[],PetscObject ptr) 627 { 628 PetscFunctionBegin; 629 if (ptr) { 630 char *tname; 631 PetscBool skipreference; 632 633 PetscCall(PetscObjectListReverseFind(ptr->olist,obj,&tname,&skipreference)); 634 if (tname) PetscCheck(skipreference,PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"An object cannot be composed with an object that was composed with it"); 635 } 636 PetscCall(PetscObjectListAdd(&obj->olist,name,ptr)); 637 PetscFunctionReturn(0); 638 } 639 640 PetscErrorCode PetscObjectQuery_Petsc(PetscObject obj,const char name[],PetscObject *ptr) 641 { 642 PetscFunctionBegin; 643 PetscValidHeader(obj,1); 644 PetscCall(PetscObjectListFind(obj->olist,name,ptr)); 645 PetscFunctionReturn(0); 646 } 647 648 PetscErrorCode PetscObjectComposeFunction_Petsc(PetscObject obj,const char name[],void (*ptr)(void)) 649 { 650 PetscFunctionBegin; 651 PetscValidHeader(obj,1); 652 PetscCall(PetscFunctionListAdd(&obj->qlist,name,ptr)); 653 PetscFunctionReturn(0); 654 } 655 656 PetscErrorCode PetscObjectQueryFunction_Petsc(PetscObject obj,const char name[],void (**ptr)(void)) 657 { 658 PetscFunctionBegin; 659 PetscValidHeader(obj,1); 660 PetscCall(PetscFunctionListFind(obj->qlist,name,ptr)); 661 PetscFunctionReturn(0); 662 } 663 664 /*@C 665 PetscObjectCompose - Associates another PETSc object with a given PETSc object. 666 667 Not Collective 668 669 Input Parameters: 670 + obj - the PETSc object; this must be cast with (PetscObject), for example, 671 PetscObjectCompose((PetscObject)mat,...); 672 . name - name associated with the child object 673 - ptr - the other PETSc object to associate with the PETSc object; this must also be 674 cast with (PetscObject) 675 676 Level: advanced 677 678 Notes: 679 The second objects reference count is automatically increased by one when it is 680 composed. 681 682 Replaces any previous object that had the same name. 683 684 If ptr is null and name has previously been composed using an object, then that 685 entry is removed from the obj. 686 687 `PetscObjectCompose()` can be used with any PETSc object (such as 688 `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object. 689 690 `PetscContainerCreate()` can be used to create an object from a 691 user-provided pointer that may then be composed with PETSc objects using `PetscObjectCompose()` 692 693 .seealso: `PetscObjectQuery()`, `PetscContainerCreate()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`, 694 `PetscContainerSetPointer()` 695 @*/ 696 PetscErrorCode PetscObjectCompose(PetscObject obj,const char name[],PetscObject ptr) 697 { 698 PetscFunctionBegin; 699 PetscValidHeader(obj,1); 700 PetscValidCharPointer(name,2); 701 if (ptr) PetscValidHeader(ptr,3); 702 PetscCheck(obj != ptr,PetscObjectComm((PetscObject)obj),PETSC_ERR_SUP,"Cannot compose object with itself"); 703 PetscCall((*obj->bops->compose)(obj,name,ptr)); 704 PetscFunctionReturn(0); 705 } 706 707 /*@C 708 PetscObjectQuery - Gets a PETSc object associated with a given object that was composed with `PetscObjectCompose()` 709 710 Not Collective 711 712 Input Parameters: 713 + obj - the PETSc object 714 Thus must be cast with a (PetscObject), for example, 715 PetscObjectCompose((PetscObject)mat,...); 716 . name - name associated with child object 717 - ptr - the other PETSc object associated with the PETSc object, this must be 718 cast with (PetscObject*) 719 720 Level: advanced 721 722 Note: 723 The reference count of neither object is increased in this call 724 725 .seealso: `PetscObjectCompose()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer` 726 `PetscContainerGetPointer()` 727 @*/ 728 PetscErrorCode PetscObjectQuery(PetscObject obj,const char name[],PetscObject *ptr) 729 { 730 PetscFunctionBegin; 731 PetscValidHeader(obj,1); 732 PetscValidCharPointer(name,2); 733 PetscValidPointer(ptr,3); 734 PetscCall((*obj->bops->query)(obj,name,ptr)); 735 PetscFunctionReturn(0); 736 } 737 738 /*MC 739 PetscObjectComposeFunction - Associates a function with a given PETSc object. 740 741 Synopsis: 742 #include <petscsys.h> 743 PetscErrorCode PetscObjectComposeFunction(PetscObject obj,const char name[],void (*fptr)(void)) 744 745 Logically Collective on PetscObject 746 747 Input Parameters: 748 + obj - the PETSc object; this must be cast with a (PetscObject), for example, 749 PetscObjectCompose((PetscObject)mat,...); 750 . name - name associated with the child function 751 . fname - name of the function 752 - fptr - function pointer 753 754 Level: advanced 755 756 Notes: 757 When the first argument of the function is the object within which it has been composed then `PetscTryMethod()` and `PetscUseMethod()` 758 can be used to call the function directly with error checking. 759 760 To remove a registered routine, pass in NULL for fptr(). 761 762 PetscObjectComposeFunction() can be used with any PETSc object (such as 763 `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object. 764 765 `PetscCallMethod()` is used to call a function that is stored in the objects obj->ops table. 766 767 .seealso: `PetscObjectQueryFunction()`, `PetscContainerCreate()` `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscTryMethod()`, `PetscUseMethod()`, 768 `PetscCallMethod()` 769 M*/ 770 771 PetscErrorCode PetscObjectComposeFunction_Private(PetscObject obj,const char name[],void (*fptr)(void)) 772 { 773 PetscFunctionBegin; 774 PetscValidHeader(obj,1); 775 PetscValidCharPointer(name,2); 776 PetscCall((*obj->bops->composefunction)(obj,name,fptr)); 777 PetscFunctionReturn(0); 778 } 779 780 /*MC 781 PetscObjectQueryFunction - Gets a function associated with a given object. 782 783 Synopsis: 784 #include <petscsys.h> 785 PetscErrorCode PetscObjectQueryFunction(PetscObject obj,const char name[],void (**fptr)(void)) 786 787 Logically Collective on PetscObject 788 789 Input Parameters: 790 + obj - the PETSc object; this must be cast with (PetscObject), for example, 791 PetscObjectQueryFunction((PetscObject)ksp,...); 792 - name - name associated with the child function 793 794 Output Parameter: 795 . fptr - function pointer 796 797 Level: advanced 798 799 .seealso: `PetscObjectComposeFunction()`, `PetscFunctionListFind()`, `PetscObjectCompose()`, `PetscObjectQuery()` 800 M*/ 801 PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj,const char name[],void (**ptr)(void)) 802 { 803 PetscFunctionBegin; 804 PetscValidHeader(obj,1); 805 PetscValidCharPointer(name,2); 806 PetscCall((*obj->bops->queryfunction)(obj,name,ptr)); 807 PetscFunctionReturn(0); 808 } 809 810 struct _p_PetscContainer { 811 PETSCHEADER(int); 812 void *ptr; 813 PetscErrorCode (*userdestroy)(void*); 814 }; 815 816 /*@C 817 PetscContainerUserDestroyDefault - Default destroy routine for user-provided data that simply calls `PetscFree()` in the data 818 provided with `PetscContainerSetPointer()` 819 820 Logically Collective on `PetscContainer` 821 822 Input Parameter: 823 . ctx - pointer to user-provided data 824 825 Level: advanced 826 827 .seealso: `PetscContainerDestroy()`, `PetscContainerSetUserDestroy()` 828 @*/ 829 PetscErrorCode PetscContainerUserDestroyDefault(void* ctx) 830 { 831 PetscFunctionBegin; 832 PetscCall(PetscFree(ctx)); 833 PetscFunctionReturn(0); 834 } 835 836 /*@C 837 PetscContainerGetPointer - Gets the pointer value contained in the container that was provided with `PetscContainerSetPointer()` 838 839 Not Collective 840 841 Input Parameter: 842 . obj - the object created with `PetscContainerCreate()` 843 844 Output Parameter: 845 . ptr - the pointer value 846 847 Level: advanced 848 849 .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, 850 `PetscContainerSetPointer()` 851 @*/ 852 PetscErrorCode PetscContainerGetPointer(PetscContainer obj,void **ptr) 853 { 854 PetscFunctionBegin; 855 PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1); 856 PetscValidPointer(ptr,2); 857 *ptr = obj->ptr; 858 PetscFunctionReturn(0); 859 } 860 861 /*@C 862 PetscContainerSetPointer - Sets the pointer value contained in the container. 863 864 Logically Collective on `PetscContainer` 865 866 Input Parameters: 867 + obj - the object created with `PetscContainerCreate()` 868 - ptr - the pointer value 869 870 Level: advanced 871 872 .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObjectCompose()`, `PetscObjectQuery()`, 873 `PetscContainerGetPointer()` 874 @*/ 875 PetscErrorCode PetscContainerSetPointer(PetscContainer obj,void *ptr) 876 { 877 PetscFunctionBegin; 878 PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1); 879 if (ptr) PetscValidPointer(ptr,2); 880 obj->ptr = ptr; 881 PetscFunctionReturn(0); 882 } 883 884 /*@C 885 PetscContainerDestroy - Destroys a PETSc container object. 886 887 Collective on `PetscContainer` 888 889 Input Parameter: 890 . obj - an object that was created with `PetscContainerCreate()` 891 892 Level: advanced 893 894 Notes: 895 If `PetscContainerSetUserDestroy()` was used to provide a user destroy object for the data provided with `PetscContainerSetPointer()` 896 then that function is called to destroy the data. 897 898 .seealso: `PetscContainerCreate()`, `PetscContainerSetUserDestroy()` 899 @*/ 900 PetscErrorCode PetscContainerDestroy(PetscContainer *obj) 901 { 902 PetscFunctionBegin; 903 if (!*obj) PetscFunctionReturn(0); 904 PetscValidHeaderSpecific(*obj,PETSC_CONTAINER_CLASSID,1); 905 if (--((PetscObject)(*obj))->refct > 0) {*obj = NULL; PetscFunctionReturn(0);} 906 if ((*obj)->userdestroy) PetscCall((*(*obj)->userdestroy)((*obj)->ptr)); 907 PetscCall(PetscHeaderDestroy(obj)); 908 PetscFunctionReturn(0); 909 } 910 911 /*@C 912 PetscContainerSetUserDestroy - Sets name of the user destroy function for the data provided to the `PetscContainer` with `PetscContainerSetPointer()` 913 914 Logically Collective on `PetscContainer` 915 916 Input Parameters: 917 + obj - an object that was created with `PetscContainerCreate()` 918 - des - name of the user destroy function 919 920 Notes: 921 Use `PetscContainerUserDestroyDefault()` if the memory was obtained by calling `PetscMalloc()` or one of its variants for single memory allocation. 922 923 Level: advanced 924 925 .seealso: `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()` 926 @*/ 927 PetscErrorCode PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void*)) 928 { 929 PetscFunctionBegin; 930 PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1); 931 obj->userdestroy = des; 932 PetscFunctionReturn(0); 933 } 934 935 PetscClassId PETSC_CONTAINER_CLASSID; 936 937 /*@C 938 PetscContainerCreate - Creates a PETSc object that has room to hold 939 a single pointer. This allows one to attach any type of data (accessible 940 through a pointer) with the `PetscObjectCompose()` function to a `PetscObject`. 941 The data item itself is attached by a call to `PetscContainerSetPointer()`. 942 943 Collective 944 945 Input Parameters: 946 . comm - MPI communicator that shares the object 947 948 Output Parameters: 949 . container - the container created 950 951 Level: advanced 952 953 .seealso: `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`, 954 `PetscContainerSetUserDestroy()` 955 @*/ 956 PetscErrorCode PetscContainerCreate(MPI_Comm comm,PetscContainer *container) 957 { 958 PetscFunctionBegin; 959 PetscValidPointer(container,2); 960 PetscCall(PetscSysInitializePackage()); 961 PetscCall(PetscHeaderCreate(*container,PETSC_CONTAINER_CLASSID,"PetscContainer","Container","Sys",comm,PetscContainerDestroy,NULL)); 962 PetscFunctionReturn(0); 963 } 964 965 /*@ 966 PetscObjectSetFromOptions - Sets generic parameters from user options. 967 968 Collective on obj 969 970 Input Parameter: 971 . obj - the `PetscObject` 972 973 Options Database Keys: 974 975 Notes: 976 We have no generic options at present, so this does nothing 977 978 Level: beginner 979 980 .seealso: `PetscObjectSetOptionsPrefix()`, `PetscObjectGetOptionsPrefix()` 981 @*/ 982 PetscErrorCode PetscObjectSetFromOptions(PetscObject obj) 983 { 984 PetscFunctionBegin; 985 PetscValidHeader(obj,1); 986 PetscFunctionReturn(0); 987 } 988 989 /*@ 990 PetscObjectSetUp - Sets up the internal data structures for the later use. 991 992 Collective on `PetscObject` 993 994 Input Parameters: 995 . obj - the `PetscObject` 996 997 Notes: 998 This does nothing at present. 999 1000 Level: advanced 1001 1002 .seealso: `PetscObjectDestroy()` 1003 @*/ 1004 PetscErrorCode PetscObjectSetUp(PetscObject obj) 1005 { 1006 PetscFunctionBegin; 1007 PetscValidHeader(obj,1); 1008 PetscFunctionReturn(0); 1009 } 1010