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 Concepts: options database^printing 283 284 @*/ 285 PetscErrorCode PetscObjectsDump(FILE *fd,PetscBool all) 286 { 287 PetscErrorCode ierr; 288 PetscInt i; 289 #if defined(PETSC_USE_DEBUG) 290 PetscInt j,k=0; 291 #endif 292 PetscObject h; 293 294 PetscFunctionBegin; 295 if (PetscObjectsCounts) { 296 ierr = PetscFPrintf(PETSC_COMM_WORLD,fd,"The following objects were never freed\n");CHKERRQ(ierr); 297 ierr = PetscFPrintf(PETSC_COMM_WORLD,fd,"-----------------------------------------\n");CHKERRQ(ierr); 298 for (i=0; i<PetscObjectsMaxCounts; i++) { 299 if ((h = PetscObjects[i])) { 300 ierr = PetscObjectName(h);CHKERRQ(ierr); 301 { 302 #if defined(PETSC_USE_DEBUG) 303 PetscStack *stack = 0; 304 char *create,*rclass; 305 306 /* if the PETSc function the user calls is not a create then this object was NOT directly created by them */ 307 ierr = PetscMallocGetStack(h,&stack);CHKERRQ(ierr); 308 if (stack) { 309 k = stack->currentsize-2; 310 if (!all) { 311 k = 0; 312 while (!stack->petscroutine[k]) k++; 313 ierr = PetscStrstr(stack->function[k],"Create",&create);CHKERRQ(ierr); 314 if (!create) { 315 ierr = PetscStrstr(stack->function[k],"Get",&create);CHKERRQ(ierr); 316 } 317 ierr = PetscStrstr(stack->function[k],h->class_name,&rclass);CHKERRQ(ierr); 318 if (!create) continue; 319 if (!rclass) continue; 320 } 321 } 322 #endif 323 324 ierr = PetscFPrintf(PETSC_COMM_WORLD,fd,"[%d] %s %s %s\n",PetscGlobalRank,h->class_name,h->type_name,h->name);CHKERRQ(ierr); 325 326 #if defined(PETSC_USE_DEBUG) 327 ierr = PetscMallocGetStack(h,&stack);CHKERRQ(ierr); 328 if (stack) { 329 for (j=k; j>=0; j--) { 330 fprintf(fd," [%d] %s() in %s\n",PetscGlobalRank,stack->function[j],stack->file[j]); 331 } 332 } 333 #endif 334 } 335 } 336 } 337 } 338 PetscFunctionReturn(0); 339 } 340 #endif 341 342 #if defined(PETSC_USE_LOG) 343 344 /*@C 345 PetscObjectsView - Prints the currently existing objects. 346 347 Logically Collective on PetscViewer 348 349 Input Parameter: 350 . viewer - must be an PETSCVIEWERASCII viewer 351 352 Level: advanced 353 354 Concepts: options database^printing 355 356 @*/ 357 PetscErrorCode PetscObjectsView(PetscViewer viewer) 358 { 359 PetscErrorCode ierr; 360 PetscBool isascii; 361 FILE *fd; 362 363 PetscFunctionBegin; 364 if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD; 365 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr); 366 if (!isascii) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Only supports ASCII viewer"); 367 ierr = PetscViewerASCIIGetPointer(viewer,&fd);CHKERRQ(ierr); 368 ierr = PetscObjectsDump(fd,PETSC_TRUE);CHKERRQ(ierr); 369 PetscFunctionReturn(0); 370 } 371 372 /*@C 373 PetscObjectsGetObject - Get a pointer to a named object 374 375 Not collective 376 377 Input Parameter: 378 . name - the name of an object 379 380 Output Parameter: 381 . obj - the object or null if there is no object 382 383 Level: advanced 384 385 Concepts: options database^printing 386 387 @*/ 388 PetscErrorCode PetscObjectsGetObject(const char *name,PetscObject *obj,char **classname) 389 { 390 PetscErrorCode ierr; 391 PetscInt i; 392 PetscObject h; 393 PetscBool flg; 394 395 PetscFunctionBegin; 396 *obj = NULL; 397 for (i=0; i<PetscObjectsMaxCounts; i++) { 398 if ((h = PetscObjects[i])) { 399 ierr = PetscObjectName(h);CHKERRQ(ierr); 400 ierr = PetscStrcmp(h->name,name,&flg);CHKERRQ(ierr); 401 if (flg) { 402 *obj = h; 403 if (classname) *classname = h->class_name; 404 PetscFunctionReturn(0); 405 } 406 } 407 } 408 PetscFunctionReturn(0); 409 } 410 #endif 411 412 /*@ 413 PetscObjectSetPrintedOptions - indicate to an object that it should behave as if it has already printed the help for its options 414 415 Input Parameters: 416 . obj - the PetscObject 417 418 Level: developer 419 420 Developer Notes: 421 This is used, for example to prevent sequential objects that are created from a parallel object; such as the KSP created by 422 PCBJACOBI from all printing the same help messages to the screen 423 424 .seealso: PetscOptionsInsert() 425 @*/ 426 PetscErrorCode PetscObjectSetPrintedOptions(PetscObject obj) 427 { 428 PetscFunctionBegin; 429 obj->optionsprinted = PETSC_TRUE; 430 PetscFunctionReturn(0); 431 } 432 433 /*@ 434 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. 435 436 Input Parameters: 437 + pobj - the parent object 438 - obj - the PetscObject 439 440 Level: developer 441 442 Developer Notes: 443 This is used, for example to prevent sequential objects that are created from a parallel object; such as the KSP created by 444 PCBJACOBI from all printing the same help messages to the screen 445 446 This will not handle more complicated situations like with GASM where children may live on any subset of the parent's processes and overlap 447 448 .seealso: PetscOptionsInsert(), PetscObjectSetPrintedOptions() 449 @*/ 450 PetscErrorCode PetscObjectInheritPrintedOptions(PetscObject pobj,PetscObject obj) 451 { 452 PetscErrorCode ierr; 453 PetscMPIInt prank,size; 454 455 PetscFunctionBegin; 456 ierr = MPI_Comm_rank(pobj->comm,&prank);CHKERRQ(ierr); 457 ierr = MPI_Comm_size(obj->comm,&size);CHKERRQ(ierr); 458 if (size == 1 && prank > 0) obj->optionsprinted = PETSC_TRUE; 459 PetscFunctionReturn(0); 460 } 461 462 /*@C 463 PetscObjectAddOptionsHandler - Adds an additional function to check for options when XXXSetFromOptions() is called. 464 465 Not Collective 466 467 Input Parameter: 468 + obj - the PETSc object 469 . handle - function that checks for options 470 . destroy - function to destroy context if provided 471 - ctx - optional context for check function 472 473 Level: developer 474 475 476 .seealso: KSPSetFromOptions(), PCSetFromOptions(), SNESSetFromOptions(), PetscObjectProcessOptionsHandlers(), PetscObjectDestroyOptionsHandlers() 477 478 @*/ 479 PetscErrorCode PetscObjectAddOptionsHandler(PetscObject obj,PetscErrorCode (*handle)(PetscOptionItems*,PetscObject,void*),PetscErrorCode (*destroy)(PetscObject,void*),void *ctx) 480 { 481 PetscFunctionBegin; 482 PetscValidHeader(obj,1); 483 if (obj->noptionhandler >= PETSC_MAX_OPTIONS_HANDLER) SETERRQ(obj->comm,PETSC_ERR_ARG_OUTOFRANGE,"To many options handlers added"); 484 obj->optionhandler[obj->noptionhandler] = handle; 485 obj->optiondestroy[obj->noptionhandler] = destroy; 486 obj->optionctx[obj->noptionhandler++] = ctx; 487 PetscFunctionReturn(0); 488 } 489 490 /*@C 491 PetscObjectProcessOptionsHandlers - Calls all the options handlers attached to an object 492 493 Not Collective 494 495 Input Parameter: 496 . obj - the PETSc object 497 498 Level: developer 499 500 501 .seealso: KSPSetFromOptions(), PCSetFromOptions(), SNESSetFromOptions(), PetscObjectAddOptionsHandler(), PetscObjectDestroyOptionsHandlers() 502 503 @*/ 504 PetscErrorCode PetscObjectProcessOptionsHandlers(PetscOptionItems *PetscOptionsObject,PetscObject obj) 505 { 506 PetscInt i; 507 PetscErrorCode ierr; 508 509 PetscFunctionBegin; 510 PetscValidHeader(obj,1); 511 for (i=0; i<obj->noptionhandler; i++) { 512 ierr = (*obj->optionhandler[i])(PetscOptionsObject,obj,obj->optionctx[i]);CHKERRQ(ierr); 513 } 514 PetscFunctionReturn(0); 515 } 516 517 /*@C 518 PetscObjectDestroyOptionsHandlers - Destroys all the option handlers attached to an object 519 520 Not Collective 521 522 Input Parameter: 523 . obj - the PETSc object 524 525 Level: developer 526 527 528 .seealso: KSPSetFromOptions(), PCSetFromOptions(), SNESSetFromOptions(), PetscObjectAddOptionsHandler(), PetscObjectProcessOptionsHandlers() 529 530 @*/ 531 PetscErrorCode PetscObjectDestroyOptionsHandlers(PetscObject obj) 532 { 533 PetscInt i; 534 PetscErrorCode ierr; 535 536 PetscFunctionBegin; 537 PetscValidHeader(obj,1); 538 for (i=0; i<obj->noptionhandler; i++) { 539 if (obj->optiondestroy[i]) { 540 ierr = (*obj->optiondestroy[i])(obj,obj->optionctx[i]);CHKERRQ(ierr); 541 } 542 } 543 obj->noptionhandler = 0; 544 PetscFunctionReturn(0); 545 } 546 547 548 /*@C 549 PetscObjectReference - Indicates to any PetscObject that it is being 550 referenced by another PetscObject. This increases the reference 551 count for that object by one. 552 553 Logically Collective on PetscObject 554 555 Input Parameter: 556 . obj - the PETSc object. This must be cast with (PetscObject), for example, 557 PetscObjectReference((PetscObject)mat); 558 559 Level: advanced 560 561 .seealso: PetscObjectCompose(), PetscObjectDereference() 562 @*/ 563 PetscErrorCode PetscObjectReference(PetscObject obj) 564 { 565 PetscFunctionBegin; 566 if (!obj) PetscFunctionReturn(0); 567 PetscValidHeader(obj,1); 568 obj->refct++; 569 PetscFunctionReturn(0); 570 } 571 572 /*@C 573 PetscObjectGetReference - Gets the current reference count for 574 any PETSc object. 575 576 Not Collective 577 578 Input Parameter: 579 . obj - the PETSc object; this must be cast with (PetscObject), for example, 580 PetscObjectGetReference((PetscObject)mat,&cnt); 581 582 Output Parameter: 583 . cnt - the reference count 584 585 Level: advanced 586 587 .seealso: PetscObjectCompose(), PetscObjectDereference(), PetscObjectReference() 588 @*/ 589 PetscErrorCode PetscObjectGetReference(PetscObject obj,PetscInt *cnt) 590 { 591 PetscFunctionBegin; 592 PetscValidHeader(obj,1); 593 PetscValidIntPointer(cnt,2); 594 *cnt = obj->refct; 595 PetscFunctionReturn(0); 596 } 597 598 /*@C 599 PetscObjectDereference - Indicates to any PetscObject that it is being 600 referenced by one less PetscObject. This decreases the reference 601 count for that object by one. 602 603 Collective on PetscObject if reference reaches 0 otherwise Logically Collective 604 605 Input Parameter: 606 . obj - the PETSc object; this must be cast with (PetscObject), for example, 607 PetscObjectDereference((PetscObject)mat); 608 609 Notes: 610 PetscObjectDestroy(PetscObject *obj) sets the obj pointer to null after the call, this routine does not. 611 612 Level: advanced 613 614 .seealso: PetscObjectCompose(), PetscObjectReference() 615 @*/ 616 PetscErrorCode PetscObjectDereference(PetscObject obj) 617 { 618 PetscErrorCode ierr; 619 620 PetscFunctionBegin; 621 if (!obj) PetscFunctionReturn(0); 622 PetscValidHeader(obj,1); 623 if (obj->bops->destroy) { 624 ierr = (*obj->bops->destroy)(&obj);CHKERRQ(ierr); 625 } else if (!--obj->refct) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"This PETSc object does not have a generic destroy routine"); 626 PetscFunctionReturn(0); 627 } 628 629 /* ----------------------------------------------------------------------- */ 630 /* 631 The following routines are the versions private to the PETSc object 632 data structures. 633 */ 634 PetscErrorCode PetscObjectGetComm_Petsc(PetscObject obj,MPI_Comm *comm) 635 { 636 PetscFunctionBegin; 637 PetscValidHeader(obj,1); 638 *comm = obj->comm; 639 PetscFunctionReturn(0); 640 } 641 642 PetscErrorCode PetscObjectRemoveReference(PetscObject obj,const char name[]) 643 { 644 PetscErrorCode ierr; 645 646 PetscFunctionBegin; 647 PetscValidHeader(obj,1); 648 ierr = PetscObjectListRemoveReference(&obj->olist,name);CHKERRQ(ierr); 649 PetscFunctionReturn(0); 650 } 651 652 PetscErrorCode PetscObjectCompose_Petsc(PetscObject obj,const char name[],PetscObject ptr) 653 { 654 PetscErrorCode ierr; 655 char *tname; 656 PetscBool skipreference; 657 658 PetscFunctionBegin; 659 if (ptr) { 660 ierr = PetscObjectListReverseFind(ptr->olist,obj,&tname,&skipreference);CHKERRQ(ierr); 661 if (tname && !skipreference) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"An object cannot be composed with an object that was composed with it"); 662 } 663 ierr = PetscObjectListAdd(&obj->olist,name,ptr);CHKERRQ(ierr); 664 PetscFunctionReturn(0); 665 } 666 667 PetscErrorCode PetscObjectQuery_Petsc(PetscObject obj,const char name[],PetscObject *ptr) 668 { 669 PetscErrorCode ierr; 670 671 PetscFunctionBegin; 672 PetscValidHeader(obj,1); 673 ierr = PetscObjectListFind(obj->olist,name,ptr);CHKERRQ(ierr); 674 PetscFunctionReturn(0); 675 } 676 677 PetscErrorCode PetscObjectComposeFunction_Petsc(PetscObject obj,const char name[],void (*ptr)(void)) 678 { 679 PetscErrorCode ierr; 680 681 PetscFunctionBegin; 682 PetscValidHeader(obj,1); 683 ierr = PetscFunctionListAdd(&obj->qlist,name,ptr);CHKERRQ(ierr); 684 PetscFunctionReturn(0); 685 } 686 687 PetscErrorCode PetscObjectQueryFunction_Petsc(PetscObject obj,const char name[],void (**ptr)(void)) 688 { 689 PetscErrorCode ierr; 690 691 PetscFunctionBegin; 692 PetscValidHeader(obj,1); 693 ierr = PetscFunctionListFind(obj->qlist,name,ptr);CHKERRQ(ierr); 694 PetscFunctionReturn(0); 695 } 696 697 /*@C 698 PetscObjectCompose - Associates another PETSc object with a given PETSc object. 699 700 Not Collective 701 702 Input Parameters: 703 + obj - the PETSc object; this must be cast with (PetscObject), for example, 704 PetscObjectCompose((PetscObject)mat,...); 705 . name - name associated with the child object 706 - ptr - the other PETSc object to associate with the PETSc object; this must also be 707 cast with (PetscObject) 708 709 Level: advanced 710 711 Notes: 712 The second objects reference count is automatically increased by one when it is 713 composed. 714 715 Replaces any previous object that had the same name. 716 717 If ptr is null and name has previously been composed using an object, then that 718 entry is removed from the obj. 719 720 PetscObjectCompose() can be used with any PETSc object (such as 721 Mat, Vec, KSP, SNES, etc.) or any user-provided object. See 722 PetscContainerCreate() for info on how to create an object from a 723 user-provided pointer that may then be composed with PETSc objects. 724 725 Concepts: objects^composing 726 Concepts: composing objects 727 728 .seealso: PetscObjectQuery(), PetscContainerCreate() 729 @*/ 730 PetscErrorCode PetscObjectCompose(PetscObject obj,const char name[],PetscObject ptr) 731 { 732 PetscErrorCode ierr; 733 734 PetscFunctionBegin; 735 PetscValidHeader(obj,1); 736 PetscValidCharPointer(name,2); 737 if (ptr) PetscValidHeader(ptr,3); 738 if (obj == ptr) SETERRQ(PetscObjectComm((PetscObject)obj),PETSC_ERR_SUP,"Cannot compose object with itself"); 739 ierr = (*obj->bops->compose)(obj,name,ptr);CHKERRQ(ierr); 740 PetscFunctionReturn(0); 741 } 742 743 /*@C 744 PetscObjectQuery - Gets a PETSc object associated with a given object. 745 746 Not Collective 747 748 Input Parameters: 749 + obj - the PETSc object 750 Thus must be cast with a (PetscObject), for example, 751 PetscObjectCompose((PetscObject)mat,...); 752 . name - name associated with child object 753 - ptr - the other PETSc object associated with the PETSc object, this must be 754 cast with (PetscObject*) 755 756 Level: advanced 757 758 The reference count of neither object is increased in this call 759 760 Concepts: objects^composing 761 Concepts: composing objects 762 Concepts: objects^querying 763 Concepts: querying objects 764 765 .seealso: PetscObjectCompose() 766 @*/ 767 PetscErrorCode PetscObjectQuery(PetscObject obj,const char name[],PetscObject *ptr) 768 { 769 PetscErrorCode ierr; 770 771 PetscFunctionBegin; 772 PetscValidHeader(obj,1); 773 PetscValidCharPointer(name,2); 774 PetscValidPointer(ptr,3); 775 ierr = (*obj->bops->query)(obj,name,ptr);CHKERRQ(ierr); 776 PetscFunctionReturn(0); 777 } 778 779 /*MC 780 PetscObjectComposeFunction - Associates a function with a given PETSc object. 781 782 Synopsis: 783 #include <petscsys.h> 784 PetscErrorCode PetscObjectComposeFunction(PetscObject obj,const char name[],void (*fptr)(void)) 785 786 Logically Collective on PetscObject 787 788 Input Parameters: 789 + obj - the PETSc object; this must be cast with a (PetscObject), for example, 790 PetscObjectCompose((PetscObject)mat,...); 791 . name - name associated with the child function 792 . fname - name of the function 793 - fptr - function pointer 794 795 Level: advanced 796 797 Notes: 798 To remove a registered routine, pass in NULL for fptr(). 799 800 PetscObjectComposeFunction() can be used with any PETSc object (such as 801 Mat, Vec, KSP, SNES, etc.) or any user-provided object. 802 803 Concepts: objects^composing functions 804 Concepts: composing functions 805 Concepts: functions^querying 806 Concepts: objects^querying 807 Concepts: querying objects 808 809 .seealso: PetscObjectQueryFunction(), PetscContainerCreate() 810 M*/ 811 812 PetscErrorCode PetscObjectComposeFunction_Private(PetscObject obj,const char name[],void (*fptr)(void)) 813 { 814 PetscErrorCode ierr; 815 816 PetscFunctionBegin; 817 PetscValidHeader(obj,1); 818 PetscValidCharPointer(name,2); 819 ierr = (*obj->bops->composefunction)(obj,name,fptr);CHKERRQ(ierr); 820 PetscFunctionReturn(0); 821 } 822 823 /*MC 824 PetscObjectQueryFunction - Gets a function associated with a given object. 825 826 Synopsis: 827 #include <petscsys.h> 828 PetscErrorCode PetscObjectQueryFunction(PetscObject obj,const char name[],void (**fptr)(void)) 829 830 Logically Collective on PetscObject 831 832 Input Parameters: 833 + obj - the PETSc object; this must be cast with (PetscObject), for example, 834 PetscObjectQueryFunction((PetscObject)ksp,...); 835 - name - name associated with the child function 836 837 Output Parameter: 838 . fptr - function pointer 839 840 Level: advanced 841 842 Concepts: objects^composing functions 843 Concepts: composing functions 844 Concepts: functions^querying 845 Concepts: objects^querying 846 Concepts: querying objects 847 848 .seealso: PetscObjectComposeFunction(), PetscFunctionListFind() 849 M*/ 850 PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj,const char name[],void (**ptr)(void)) 851 { 852 PetscErrorCode ierr; 853 854 PetscFunctionBegin; 855 PetscValidHeader(obj,1); 856 PetscValidCharPointer(name,2); 857 ierr = (*obj->bops->queryfunction)(obj,name,ptr);CHKERRQ(ierr); 858 PetscFunctionReturn(0); 859 } 860 861 struct _p_PetscContainer { 862 PETSCHEADER(int); 863 void *ptr; 864 PetscErrorCode (*userdestroy)(void*); 865 }; 866 867 /*@C 868 PetscContainerUserDestroyDefault - Default destroy routine for user-provided data that simply calls PetscFree(). 869 870 Logically Collective on PetscContainer 871 872 Input Parameter: 873 . ctx - pointer to user-provided data 874 875 Level: advanced 876 877 .seealso: PetscContainerDestroy(), PetscContainterSetUserDestroy() 878 @*/ 879 PetscErrorCode PetscContainerUserDestroyDefault(void* ctx) 880 { 881 PetscErrorCode ierr; 882 883 PetscFunctionBegin; 884 ierr = PetscFree(ctx);CHKERRQ(ierr); 885 PetscFunctionReturn(0); 886 } 887 888 /*@C 889 PetscContainerGetPointer - Gets the pointer value contained in the container. 890 891 Not Collective 892 893 Input Parameter: 894 . obj - the object created with PetscContainerCreate() 895 896 Output Parameter: 897 . ptr - the pointer value 898 899 Level: advanced 900 901 .seealso: PetscContainerCreate(), PetscContainerDestroy(), 902 PetscContainerSetPointer() 903 @*/ 904 PetscErrorCode PetscContainerGetPointer(PetscContainer obj,void **ptr) 905 { 906 PetscFunctionBegin; 907 PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1); 908 PetscValidPointer(ptr,2); 909 *ptr = obj->ptr; 910 PetscFunctionReturn(0); 911 } 912 913 914 /*@C 915 PetscContainerSetPointer - Sets the pointer value contained in the container. 916 917 Logically Collective on PetscContainer 918 919 Input Parameters: 920 + obj - the object created with PetscContainerCreate() 921 - ptr - the pointer value 922 923 Level: advanced 924 925 .seealso: PetscContainerCreate(), PetscContainerDestroy(), 926 PetscContainerGetPointer() 927 @*/ 928 PetscErrorCode PetscContainerSetPointer(PetscContainer obj,void *ptr) 929 { 930 PetscFunctionBegin; 931 PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1); 932 if (ptr) PetscValidPointer(ptr,2); 933 obj->ptr = ptr; 934 PetscFunctionReturn(0); 935 } 936 937 /*@C 938 PetscContainerDestroy - Destroys a PETSc container object. 939 940 Collective on PetscContainer 941 942 Input Parameter: 943 . obj - an object that was created with PetscContainerCreate() 944 945 Level: advanced 946 947 .seealso: PetscContainerCreate(), PetscContainerSetUserDestroy() 948 @*/ 949 PetscErrorCode PetscContainerDestroy(PetscContainer *obj) 950 { 951 PetscErrorCode ierr; 952 953 PetscFunctionBegin; 954 if (!*obj) PetscFunctionReturn(0); 955 PetscValidHeaderSpecific(*obj,PETSC_CONTAINER_CLASSID,1); 956 if (--((PetscObject)(*obj))->refct > 0) {*obj = 0; PetscFunctionReturn(0);} 957 if ((*obj)->userdestroy) { ierr = (*(*obj)->userdestroy)((*obj)->ptr);CHKERRQ(ierr); } 958 ierr = PetscHeaderDestroy(obj);CHKERRQ(ierr); 959 PetscFunctionReturn(0); 960 } 961 962 /*@C 963 PetscContainerSetUserDestroy - Sets name of the user destroy function. 964 965 Logically Collective on PetscContainer 966 967 Input Parameter: 968 + obj - an object that was created with PetscContainerCreate() 969 - des - name of the user destroy function 970 971 Notes: 972 Use PetscContainerUserDestroyDefault() if the memory was obtained by calling PetscMalloc or one of its variants for single memory allocation. 973 974 Level: advanced 975 976 .seealso: PetscContainerDestroy(), PetscContainerUserDestroyDefault(), PetscMalloc(), PetscMalloc1(), PetscCalloc(), PetscCalloc1() 977 @*/ 978 PetscErrorCode PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void*)) 979 { 980 PetscFunctionBegin; 981 PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1); 982 obj->userdestroy = des; 983 PetscFunctionReturn(0); 984 } 985 986 PetscClassId PETSC_CONTAINER_CLASSID; 987 988 /*@C 989 PetscContainerCreate - Creates a PETSc object that has room to hold 990 a single pointer. This allows one to attach any type of data (accessible 991 through a pointer) with the PetscObjectCompose() function to a PetscObject. 992 The data item itself is attached by a call to PetscContainerSetPointer(). 993 994 Collective on MPI_Comm 995 996 Input Parameters: 997 . comm - MPI communicator that shares the object 998 999 Output Parameters: 1000 . container - the container created 1001 1002 Level: advanced 1003 1004 .seealso: PetscContainerDestroy(), PetscContainerSetPointer(), PetscContainerGetPointer() 1005 @*/ 1006 PetscErrorCode PetscContainerCreate(MPI_Comm comm,PetscContainer *container) 1007 { 1008 PetscErrorCode ierr; 1009 PetscContainer contain; 1010 1011 PetscFunctionBegin; 1012 PetscValidPointer(container,2); 1013 ierr = PetscSysInitializePackage();CHKERRQ(ierr); 1014 ierr = PetscHeaderCreate(contain,PETSC_CONTAINER_CLASSID,"PetscContainer","Container","Sys",comm,PetscContainerDestroy,NULL);CHKERRQ(ierr); 1015 *container = contain; 1016 PetscFunctionReturn(0); 1017 } 1018 1019 /*@ 1020 PetscObjectSetFromOptions - Sets generic parameters from user options. 1021 1022 Collective on obj 1023 1024 Input Parameter: 1025 . obj - the PetscObjcet 1026 1027 Options Database Keys: 1028 1029 Notes: 1030 We have no generic options at present, so this does nothing 1031 1032 Level: beginner 1033 1034 .seealso: PetscObjectSetOptionsPrefix(), PetscObjectGetOptionsPrefix() 1035 @*/ 1036 PetscErrorCode PetscObjectSetFromOptions(PetscObject obj) 1037 { 1038 PetscFunctionBegin; 1039 PetscValidHeader(obj,1); 1040 PetscFunctionReturn(0); 1041 } 1042 1043 /*@ 1044 PetscObjectSetUp - Sets up the internal data structures for the later use. 1045 1046 Collective on PetscObject 1047 1048 Input Parameters: 1049 . obj - the PetscObject 1050 1051 Notes: 1052 This does nothing at present. 1053 1054 Level: advanced 1055 1056 .seealso: PetscObjectDestroy() 1057 @*/ 1058 PetscErrorCode PetscObjectSetUp(PetscObject obj) 1059 { 1060 PetscFunctionBegin; 1061 PetscValidHeader(obj,1); 1062 PetscFunctionReturn(0); 1063 } 1064