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