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