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 Parameters: 486 + PetscOptionsObject - this is produced by the `PetscOptionsBegin()` macro 487 - obj - the PETSc object 488 489 Level: developer 490 491 .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectDestroyOptionsHandlers()` 492 493 @*/ 494 PetscErrorCode PetscObjectProcessOptionsHandlers(PetscOptionItems *PetscOptionsObject,PetscObject obj) 495 { 496 PetscFunctionBegin; 497 PetscValidHeader(obj,2); 498 for (PetscInt i=0; i<obj->noptionhandler; i++) PetscCall((*obj->optionhandler[i])(PetscOptionsObject,obj,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 To remove a registered routine, pass in NULL for fptr(). 758 759 PetscObjectComposeFunction() can be used with any PETSc object (such as 760 `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object. 761 762 .seealso: `PetscObjectQueryFunction()`, `PetscContainerCreate()` `PetscObjectCompose()`, `PetscObjectQuery()` 763 M*/ 764 765 PetscErrorCode PetscObjectComposeFunction_Private(PetscObject obj,const char name[],void (*fptr)(void)) 766 { 767 PetscFunctionBegin; 768 PetscValidHeader(obj,1); 769 PetscValidCharPointer(name,2); 770 PetscCall((*obj->bops->composefunction)(obj,name,fptr)); 771 PetscFunctionReturn(0); 772 } 773 774 /*MC 775 PetscObjectQueryFunction - Gets a function associated with a given object. 776 777 Synopsis: 778 #include <petscsys.h> 779 PetscErrorCode PetscObjectQueryFunction(PetscObject obj,const char name[],void (**fptr)(void)) 780 781 Logically Collective on PetscObject 782 783 Input Parameters: 784 + obj - the PETSc object; this must be cast with (PetscObject), for example, 785 PetscObjectQueryFunction((PetscObject)ksp,...); 786 - name - name associated with the child function 787 788 Output Parameter: 789 . fptr - function pointer 790 791 Level: advanced 792 793 .seealso: `PetscObjectComposeFunction()`, `PetscFunctionListFind()`, `PetscObjectCompose()`, `PetscObjectQuery()` 794 M*/ 795 PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj,const char name[],void (**ptr)(void)) 796 { 797 PetscFunctionBegin; 798 PetscValidHeader(obj,1); 799 PetscValidCharPointer(name,2); 800 PetscCall((*obj->bops->queryfunction)(obj,name,ptr)); 801 PetscFunctionReturn(0); 802 } 803 804 struct _p_PetscContainer { 805 PETSCHEADER(int); 806 void *ptr; 807 PetscErrorCode (*userdestroy)(void*); 808 }; 809 810 /*@C 811 PetscContainerUserDestroyDefault - Default destroy routine for user-provided data that simply calls `PetscFree()` in the data 812 provided with `PetscContainerSetPointer()` 813 814 Logically Collective on `PetscContainer` 815 816 Input Parameter: 817 . ctx - pointer to user-provided data 818 819 Level: advanced 820 821 .seealso: `PetscContainerDestroy()`, `PetscContainerSetUserDestroy()` 822 @*/ 823 PetscErrorCode PetscContainerUserDestroyDefault(void* ctx) 824 { 825 PetscFunctionBegin; 826 PetscCall(PetscFree(ctx)); 827 PetscFunctionReturn(0); 828 } 829 830 /*@C 831 PetscContainerGetPointer - Gets the pointer value contained in the container that was provided with `PetscContainerSetPointer()` 832 833 Not Collective 834 835 Input Parameter: 836 . obj - the object created with `PetscContainerCreate()` 837 838 Output Parameter: 839 . ptr - the pointer value 840 841 Level: advanced 842 843 .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, 844 `PetscContainerSetPointer()` 845 @*/ 846 PetscErrorCode PetscContainerGetPointer(PetscContainer obj,void **ptr) 847 { 848 PetscFunctionBegin; 849 PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1); 850 PetscValidPointer(ptr,2); 851 *ptr = obj->ptr; 852 PetscFunctionReturn(0); 853 } 854 855 /*@C 856 PetscContainerSetPointer - Sets the pointer value contained in the container. 857 858 Logically Collective on `PetscContainer` 859 860 Input Parameters: 861 + obj - the object created with `PetscContainerCreate()` 862 - ptr - the pointer value 863 864 Level: advanced 865 866 .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObjectCompose()`, `PetscObjectQuery()`, 867 `PetscContainerGetPointer()` 868 @*/ 869 PetscErrorCode PetscContainerSetPointer(PetscContainer obj,void *ptr) 870 { 871 PetscFunctionBegin; 872 PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1); 873 if (ptr) PetscValidPointer(ptr,2); 874 obj->ptr = ptr; 875 PetscFunctionReturn(0); 876 } 877 878 /*@C 879 PetscContainerDestroy - Destroys a PETSc container object. 880 881 Collective on `PetscContainer` 882 883 Input Parameter: 884 . obj - an object that was created with `PetscContainerCreate()` 885 886 Level: advanced 887 888 Notes: 889 If `PetscContainerSetUserDestroy()` was used to provide a user destroy object for the data provided with `PetscContainerSetPointer()` 890 then that function is called to destroy the data. 891 892 .seealso: `PetscContainerCreate()`, `PetscContainerSetUserDestroy()` 893 @*/ 894 PetscErrorCode PetscContainerDestroy(PetscContainer *obj) 895 { 896 PetscFunctionBegin; 897 if (!*obj) PetscFunctionReturn(0); 898 PetscValidHeaderSpecific(*obj,PETSC_CONTAINER_CLASSID,1); 899 if (--((PetscObject)(*obj))->refct > 0) {*obj = NULL; PetscFunctionReturn(0);} 900 if ((*obj)->userdestroy) PetscCall((*(*obj)->userdestroy)((*obj)->ptr)); 901 PetscCall(PetscHeaderDestroy(obj)); 902 PetscFunctionReturn(0); 903 } 904 905 /*@C 906 PetscContainerSetUserDestroy - Sets name of the user destroy function for the data provided to the `PetscContainer` with `PetscContainerSetPointer()` 907 908 Logically Collective on `PetscContainer` 909 910 Input Parameters: 911 + obj - an object that was created with `PetscContainerCreate()` 912 - des - name of the user destroy function 913 914 Notes: 915 Use `PetscContainerUserDestroyDefault()` if the memory was obtained by calling `PetscMalloc()` or one of its variants for single memory allocation. 916 917 Level: advanced 918 919 .seealso: `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()` 920 @*/ 921 PetscErrorCode PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void*)) 922 { 923 PetscFunctionBegin; 924 PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1); 925 obj->userdestroy = des; 926 PetscFunctionReturn(0); 927 } 928 929 PetscClassId PETSC_CONTAINER_CLASSID; 930 931 /*@C 932 PetscContainerCreate - Creates a PETSc object that has room to hold 933 a single pointer. This allows one to attach any type of data (accessible 934 through a pointer) with the `PetscObjectCompose()` function to a `PetscObject`. 935 The data item itself is attached by a call to `PetscContainerSetPointer()`. 936 937 Collective 938 939 Input Parameters: 940 . comm - MPI communicator that shares the object 941 942 Output Parameters: 943 . container - the container created 944 945 Level: advanced 946 947 .seealso: `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`, 948 `PetscContainerSetUserDestroy()` 949 @*/ 950 PetscErrorCode PetscContainerCreate(MPI_Comm comm,PetscContainer *container) 951 { 952 PetscFunctionBegin; 953 PetscValidPointer(container,2); 954 PetscCall(PetscSysInitializePackage()); 955 PetscCall(PetscHeaderCreate(*container,PETSC_CONTAINER_CLASSID,"PetscContainer","Container","Sys",comm,PetscContainerDestroy,NULL)); 956 PetscFunctionReturn(0); 957 } 958 959 /*@ 960 PetscObjectSetFromOptions - Sets generic parameters from user options. 961 962 Collective on obj 963 964 Input Parameter: 965 . obj - the `PetscObject` 966 967 Options Database Keys: 968 969 Notes: 970 We have no generic options at present, so this does nothing 971 972 Level: beginner 973 974 .seealso: `PetscObjectSetOptionsPrefix()`, `PetscObjectGetOptionsPrefix()` 975 @*/ 976 PetscErrorCode PetscObjectSetFromOptions(PetscObject obj) 977 { 978 PetscFunctionBegin; 979 PetscValidHeader(obj,1); 980 PetscFunctionReturn(0); 981 } 982 983 /*@ 984 PetscObjectSetUp - Sets up the internal data structures for the later use. 985 986 Collective on `PetscObject` 987 988 Input Parameters: 989 . obj - the `PetscObject` 990 991 Notes: 992 This does nothing at present. 993 994 Level: advanced 995 996 .seealso: `PetscObjectDestroy()` 997 @*/ 998 PetscErrorCode PetscObjectSetUp(PetscObject obj) 999 { 1000 PetscFunctionBegin; 1001 PetscValidHeader(obj,1); 1002 PetscFunctionReturn(0); 1003 } 1004