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