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 GASM 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(PetscObject *obj) sets the obj pointer to null after the call, this routine does not. 588 589 Level: advanced 590 591 .seealso: `PetscObjectCompose()`, `PetscObjectReference()` 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. See 688 PetscContainerCreate() for info on how to create an object from a 689 user-provided pointer that may then be composed with PETSc objects. 690 691 .seealso: `PetscObjectQuery()`, `PetscContainerCreate()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()` 692 @*/ 693 PetscErrorCode PetscObjectCompose(PetscObject obj,const char name[],PetscObject ptr) 694 { 695 PetscFunctionBegin; 696 PetscValidHeader(obj,1); 697 PetscValidCharPointer(name,2); 698 if (ptr) PetscValidHeader(ptr,3); 699 PetscCheck(obj != ptr,PetscObjectComm((PetscObject)obj),PETSC_ERR_SUP,"Cannot compose object with itself"); 700 PetscCall((*obj->bops->compose)(obj,name,ptr)); 701 PetscFunctionReturn(0); 702 } 703 704 /*@C 705 PetscObjectQuery - Gets a PETSc object associated with a given object. 706 707 Not Collective 708 709 Input Parameters: 710 + obj - the PETSc object 711 Thus must be cast with a (PetscObject), for example, 712 PetscObjectCompose((PetscObject)mat,...); 713 . name - name associated with child object 714 - ptr - the other PETSc object associated with the PETSc object, this must be 715 cast with (PetscObject*) 716 717 Level: advanced 718 719 The reference count of neither object is increased in this call 720 721 .seealso: `PetscObjectCompose()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()` 722 @*/ 723 PetscErrorCode PetscObjectQuery(PetscObject obj,const char name[],PetscObject *ptr) 724 { 725 PetscFunctionBegin; 726 PetscValidHeader(obj,1); 727 PetscValidCharPointer(name,2); 728 PetscValidPointer(ptr,3); 729 PetscCall((*obj->bops->query)(obj,name,ptr)); 730 PetscFunctionReturn(0); 731 } 732 733 /*MC 734 PetscObjectComposeFunction - Associates a function with a given PETSc object. 735 736 Synopsis: 737 #include <petscsys.h> 738 PetscErrorCode PetscObjectComposeFunction(PetscObject obj,const char name[],void (*fptr)(void)) 739 740 Logically Collective on PetscObject 741 742 Input Parameters: 743 + obj - the PETSc object; this must be cast with a (PetscObject), for example, 744 PetscObjectCompose((PetscObject)mat,...); 745 . name - name associated with the child function 746 . fname - name of the function 747 - fptr - function pointer 748 749 Level: advanced 750 751 Notes: 752 To remove a registered routine, pass in NULL for fptr(). 753 754 PetscObjectComposeFunction() can be used with any PETSc object (such as 755 Mat, Vec, KSP, SNES, etc.) or any user-provided object. 756 757 .seealso: `PetscObjectQueryFunction()`, `PetscContainerCreate()` `PetscObjectCompose()`, `PetscObjectQuery()` 758 M*/ 759 760 PetscErrorCode PetscObjectComposeFunction_Private(PetscObject obj,const char name[],void (*fptr)(void)) 761 { 762 PetscFunctionBegin; 763 PetscValidHeader(obj,1); 764 PetscValidCharPointer(name,2); 765 PetscCall((*obj->bops->composefunction)(obj,name,fptr)); 766 PetscFunctionReturn(0); 767 } 768 769 /*MC 770 PetscObjectQueryFunction - Gets a function associated with a given object. 771 772 Synopsis: 773 #include <petscsys.h> 774 PetscErrorCode PetscObjectQueryFunction(PetscObject obj,const char name[],void (**fptr)(void)) 775 776 Logically Collective on PetscObject 777 778 Input Parameters: 779 + obj - the PETSc object; this must be cast with (PetscObject), for example, 780 PetscObjectQueryFunction((PetscObject)ksp,...); 781 - name - name associated with the child function 782 783 Output Parameter: 784 . fptr - function pointer 785 786 Level: advanced 787 788 .seealso: `PetscObjectComposeFunction()`, `PetscFunctionListFind()`, `PetscObjectCompose()`, `PetscObjectQuery()` 789 M*/ 790 PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj,const char name[],void (**ptr)(void)) 791 { 792 PetscFunctionBegin; 793 PetscValidHeader(obj,1); 794 PetscValidCharPointer(name,2); 795 PetscCall((*obj->bops->queryfunction)(obj,name,ptr)); 796 PetscFunctionReturn(0); 797 } 798 799 struct _p_PetscContainer { 800 PETSCHEADER(int); 801 void *ptr; 802 PetscErrorCode (*userdestroy)(void*); 803 }; 804 805 /*@C 806 PetscContainerUserDestroyDefault - Default destroy routine for user-provided data that simply calls PetscFree(). 807 808 Logically Collective on PetscContainer 809 810 Input Parameter: 811 . ctx - pointer to user-provided data 812 813 Level: advanced 814 815 .seealso: `PetscContainerDestroy()`, `PetscContainerSetUserDestroy()` 816 @*/ 817 PetscErrorCode PetscContainerUserDestroyDefault(void* ctx) 818 { 819 PetscFunctionBegin; 820 PetscCall(PetscFree(ctx)); 821 PetscFunctionReturn(0); 822 } 823 824 /*@C 825 PetscContainerGetPointer - Gets the pointer value contained in the container. 826 827 Not Collective 828 829 Input Parameter: 830 . obj - the object created with PetscContainerCreate() 831 832 Output Parameter: 833 . ptr - the pointer value 834 835 Level: advanced 836 837 .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, 838 `PetscContainerSetPointer()` 839 @*/ 840 PetscErrorCode PetscContainerGetPointer(PetscContainer obj,void **ptr) 841 { 842 PetscFunctionBegin; 843 PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1); 844 PetscValidPointer(ptr,2); 845 *ptr = obj->ptr; 846 PetscFunctionReturn(0); 847 } 848 849 /*@C 850 PetscContainerSetPointer - Sets the pointer value contained in the container. 851 852 Logically Collective on PetscContainer 853 854 Input Parameters: 855 + obj - the object created with PetscContainerCreate() 856 - ptr - the pointer value 857 858 Level: advanced 859 860 .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, 861 `PetscContainerGetPointer()` 862 @*/ 863 PetscErrorCode PetscContainerSetPointer(PetscContainer obj,void *ptr) 864 { 865 PetscFunctionBegin; 866 PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1); 867 if (ptr) PetscValidPointer(ptr,2); 868 obj->ptr = ptr; 869 PetscFunctionReturn(0); 870 } 871 872 /*@C 873 PetscContainerDestroy - Destroys a PETSc container object. 874 875 Collective on PetscContainer 876 877 Input Parameter: 878 . obj - an object that was created with PetscContainerCreate() 879 880 Level: advanced 881 882 .seealso: `PetscContainerCreate()`, `PetscContainerSetUserDestroy()` 883 @*/ 884 PetscErrorCode PetscContainerDestroy(PetscContainer *obj) 885 { 886 PetscFunctionBegin; 887 if (!*obj) PetscFunctionReturn(0); 888 PetscValidHeaderSpecific(*obj,PETSC_CONTAINER_CLASSID,1); 889 if (--((PetscObject)(*obj))->refct > 0) {*obj = NULL; PetscFunctionReturn(0);} 890 if ((*obj)->userdestroy) PetscCall((*(*obj)->userdestroy)((*obj)->ptr)); 891 PetscCall(PetscHeaderDestroy(obj)); 892 PetscFunctionReturn(0); 893 } 894 895 /*@C 896 PetscContainerSetUserDestroy - Sets name of the user destroy function. 897 898 Logically Collective on PetscContainer 899 900 Input Parameters: 901 + obj - an object that was created with PetscContainerCreate() 902 - des - name of the user destroy function 903 904 Notes: 905 Use PetscContainerUserDestroyDefault() if the memory was obtained by calling PetscMalloc or one of its variants for single memory allocation. 906 907 Level: advanced 908 909 .seealso: `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()` 910 @*/ 911 PetscErrorCode PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void*)) 912 { 913 PetscFunctionBegin; 914 PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1); 915 obj->userdestroy = des; 916 PetscFunctionReturn(0); 917 } 918 919 PetscClassId PETSC_CONTAINER_CLASSID; 920 921 /*@C 922 PetscContainerCreate - Creates a PETSc object that has room to hold 923 a single pointer. This allows one to attach any type of data (accessible 924 through a pointer) with the PetscObjectCompose() function to a PetscObject. 925 The data item itself is attached by a call to PetscContainerSetPointer(). 926 927 Collective 928 929 Input Parameters: 930 . comm - MPI communicator that shares the object 931 932 Output Parameters: 933 . container - the container created 934 935 Level: advanced 936 937 .seealso: `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`, 938 `PetscContainerSetUserDestroy()` 939 @*/ 940 PetscErrorCode PetscContainerCreate(MPI_Comm comm,PetscContainer *container) 941 { 942 PetscFunctionBegin; 943 PetscValidPointer(container,2); 944 PetscCall(PetscSysInitializePackage()); 945 PetscCall(PetscHeaderCreate(*container,PETSC_CONTAINER_CLASSID,"PetscContainer","Container","Sys",comm,PetscContainerDestroy,NULL)); 946 PetscFunctionReturn(0); 947 } 948 949 /*@ 950 PetscObjectSetFromOptions - Sets generic parameters from user options. 951 952 Collective on obj 953 954 Input Parameter: 955 . obj - the PetscObjcet 956 957 Options Database Keys: 958 959 Notes: 960 We have no generic options at present, so this does nothing 961 962 Level: beginner 963 964 .seealso: `PetscObjectSetOptionsPrefix()`, `PetscObjectGetOptionsPrefix()` 965 @*/ 966 PetscErrorCode PetscObjectSetFromOptions(PetscObject obj) 967 { 968 PetscFunctionBegin; 969 PetscValidHeader(obj,1); 970 PetscFunctionReturn(0); 971 } 972 973 /*@ 974 PetscObjectSetUp - Sets up the internal data structures for the later use. 975 976 Collective on PetscObject 977 978 Input Parameters: 979 . obj - the PetscObject 980 981 Notes: 982 This does nothing at present. 983 984 Level: advanced 985 986 .seealso: `PetscObjectDestroy()` 987 @*/ 988 PetscErrorCode PetscObjectSetUp(PetscObject obj) 989 { 990 PetscFunctionBegin; 991 PetscValidHeader(obj,1); 992 PetscFunctionReturn(0); 993 } 994