Actual source code: inherit.c

  2: /*
  3:      Provides utility routines for manipulating any type of PETSc object.
  4: */
  5: #include <petscsys.h>  /*I   "petscsys.h"    I*/

  7: PetscObject *PetscObjects = 0;
  8: PetscInt    PetscObjectsCounts = 0, PetscObjectsMaxCounts = 0;


 18: /*
 19:    PetscHeaderCreate_Private - Creates a base PETSc object header and fills
 20:    in the default values.  Called by the macro PetscHeaderCreate().
 21: */
 22: PetscErrorCode  PetscHeaderCreate_Private(PetscObject h,PetscClassId classid,PetscInt type,const char class_name[],const char descr[],const char mansec[],
 23:                                           MPI_Comm comm,PetscErrorCode (*des)(PetscObject*),PetscErrorCode (*vie)(PetscObject,PetscViewer))
 24: {
 25:   static PetscInt idcnt = 1;
 26:   PetscErrorCode  ierr;
 27:   PetscObject     *newPetscObjects;
 28:   PetscInt         newPetscObjectsMaxCounts,i;

 31:   h->classid                = classid;
 32:   h->type                   = type;
 33:   h->class_name             = (char*)class_name;
 34:   h->description            = (char*)descr;
 35:   h->mansec                 = (char*)mansec;
 36:   h->prefix                 = 0;
 37:   h->refct                  = 1;
 38:   h->amem                   = -1;
 39:   h->id                     = idcnt++;
 40:   h->parentid               = 0;
 41:   h->qlist                  = 0;
 42:   h->olist                  = 0;
 43:   h->precision              = (PetscPrecision) sizeof(PetscScalar);
 44:   h->bops->destroy          = des;
 45:   h->bops->view             = vie;
 46:   h->bops->getcomm          = PetscObjectGetComm_Petsc;
 47:   h->bops->compose          = PetscObjectCompose_Petsc;
 48:   h->bops->query            = PetscObjectQuery_Petsc;
 49:   h->bops->composefunction  = PetscObjectComposeFunction_Petsc;
 50:   h->bops->queryfunction    = PetscObjectQueryFunction_Petsc;
 51:   PetscCommDuplicate(comm,&h->comm,&h->tag);

 53:   /* Keep a record of object created */
 54:   PetscObjectsCounts++;
 55:   for (i=0; i<PetscObjectsMaxCounts; i++) {
 56:     if (!PetscObjects[i]) {
 57:       PetscObjects[i] = h;
 58:       return(0);
 59:     }
 60:   }
 61:   /* Need to increase the space for storing PETSc objects */
 62:   if (!PetscObjectsMaxCounts) newPetscObjectsMaxCounts = 100;
 63:   else                        newPetscObjectsMaxCounts = 2*PetscObjectsMaxCounts;
 64:   PetscMalloc(newPetscObjectsMaxCounts*sizeof(PetscObject),&newPetscObjects);
 65:   PetscMemcpy(newPetscObjects,PetscObjects,PetscObjectsMaxCounts*sizeof(PetscObject));
 66:   PetscMemzero(newPetscObjects+PetscObjectsMaxCounts,(newPetscObjectsMaxCounts - PetscObjectsMaxCounts)*sizeof(PetscObject));
 67:   PetscFree(PetscObjects);
 68:   PetscObjects                        = newPetscObjects;
 69:   PetscObjects[PetscObjectsMaxCounts] = h;
 70:   PetscObjectsMaxCounts               = newPetscObjectsMaxCounts;

 72:   return(0);
 73: }


 80: /*
 81:     PetscHeaderDestroy_Private - Destroys a base PETSc object header. Called by 
 82:     the macro PetscHeaderDestroy().
 83: */
 84: PetscErrorCode  PetscHeaderDestroy_Private(PetscObject h)
 85: {
 87:   PetscInt       i;

 90: #if defined(PETSC_HAVE_AMS)
 91:   if (PetscAMSPublishAll) {
 92:     PetscObjectUnPublish((PetscObject)h);
 93:   }
 94: #endif
 95:   if (PetscMemoryCollectMaximumUsage) {
 96:     PetscLogDouble usage;
 97:     PetscMemoryGetCurrentUsage(&usage);
 98:     if (usage > PetscMemoryMaximumUsage) PetscMemoryMaximumUsage = usage;
 99:   }
100:   /* first destroy things that could execute arbitrary code */
101:   if (h->python_destroy) {
102:     void           *python_context          = h->python_context;
103:     PetscErrorCode (*python_destroy)(void*) = h->python_destroy;
104:     h->python_context = 0;
105:     h->python_destroy = 0;
106:     (*python_destroy)(python_context);
107:   }
108:   PetscOListDestroy(&h->olist);
109:   PetscCommDestroy(&h->comm);
110:   /* next destroy other things */
111:   h->classid = PETSCFREEDHEADER;
112:   PetscFree(h->bops);
113:   PetscFListDestroy(&h->qlist);
114:   PetscFree(h->type_name);
115:   PetscFree(h->name);
116:   PetscFree(h->prefix);
117:   PetscFree(h->fortran_func_pointers);

119:   /* Record object removal from list of all objects */
120:   for (i=0; i<PetscObjectsMaxCounts; i++) {
121:     if (PetscObjects[i] == h) {
122:       PetscObjects[i] = 0;
123:       PetscObjectsCounts--;
124:       break;
125:     }
126:   }
127:   if (!PetscObjectsCounts) {
128:     PetscFree(PetscObjects);
129:     PetscObjectsMaxCounts = 0;
130:   }
131:   return(0);
132: }

136: /*@C
137:    PetscObjectsView - Prints the currently existing objects.

139:    Logically Collective on PetscViewer

141:    Input Parameter:
142: .  viewer - must be an PETSCVIEWERASCII viewer

144:    Level: advanced

146:    Concepts: options database^printing

148: @*/
149: PetscErrorCode  PetscObjectsView(PetscViewer viewer)
150: {
152:   PetscInt       i;
153:   PetscBool      isascii;
154:   PetscObject    h;

157:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
158:   PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
159:   if (!isascii) SETERRQ(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"Only supports ASCII viewer");

161:   for (i=0; i<PetscObjectsMaxCounts; i++) {
162:     if ((h = PetscObjects[i])) {
163:       PetscObjectName(h);
164:       PetscViewerASCIIPrintf(viewer,"%s %s %s\n",h->class_name,h->type_name,h->name);
165:     }
166:   }
167:   return(0);
168: }

172: /*@C
173:    PetscObjectsGetObject - Get a pointer to a named object

175:    Not collective

177:    Input Parameter:
178: .  name - the name of an object

180:    Output Parameter:
181: .   obj - the object or null if there is no object

183:    Level: advanced

185:    Concepts: options database^printing

187: @*/
188: PetscErrorCode  PetscObjectsGetObject(const char* name,PetscObject *obj,char **classname)
189: {
191:   PetscInt       i;
192:   PetscObject    h;
193:   PetscBool      flg;

196:   *obj = PETSC_NULL;
197:   for (i=0; i<PetscObjectsMaxCounts; i++) {
198:     if ((h = PetscObjects[i])) {
199:       PetscObjectName(h);
200:       PetscStrcmp(h->name,name,&flg);
201:       if (flg) {
202:         *obj = h;
203:         if (classname) *classname = h->class_name;
204:         return(0);
205:       }
206:     }
207:   }
208:   return(0);
209: }

213: char* PetscObjectsGetObjectMatlab(const char* name,PetscObject *obj)
214: {
216:   PetscInt       i;
217:   PetscObject    h;
218:   PetscBool      flg;

221:   *obj = PETSC_NULL;
222:   for (i=0; i<PetscObjectsMaxCounts; i++) {
223:     if ((h = PetscObjects[i])) {
224:       PetscObjectName(h);if (ierr) return(0);
225:       PetscStrcmp(h->name,name,&flg);if (ierr) return(0);
226:       if (flg) {
227:         *obj = h;
228:         PetscFunctionReturn(h->class_name);
229:       }
230:     }
231:   }
232:   return(0);
233: }

237: /*@C
238:     PetscObjectAddOptionsHandler - Adds an additional function to check for options when XXXSetFromOptions() is called.

240:     Not Collective

242:     Input Parameter:
243: +   obj - the PETSc object
244: .   handle - function that checks for options
245: .   destroy - function to destroy context if provided
246: -   ctx - optional context for check function

248:     Level: developer


251: .seealso: KSPSetFromOptions(), PCSetFromOptions(), SNESSetFromOptions(), PetscObjectProcessOptionsHandlers(), PetscObjectDestroyOptionsHandlers()

253: @*/
254: PetscErrorCode  PetscObjectAddOptionsHandler(PetscObject obj,PetscErrorCode (*handle)(PetscObject,void*),PetscErrorCode (*destroy)(PetscObject,void*),void *ctx)
255: {
257:   if (obj->noptionhandler >= PETSC_MAX_OPTIONS_HANDLER) SETERRQ(obj->comm,PETSC_ERR_ARG_OUTOFRANGE,"To many options handlers added");
258:   obj->optionhandler[obj->noptionhandler]   = handle;
259:   obj->optiondestroy[obj->noptionhandler]   = destroy;
260:   obj->optionctx[obj->noptionhandler++]     = ctx;
261:   return(0);
262: }

266: /*@C
267:     PetscObjectProcessOptionsHandlers - Calls all the options handler attached to an object

269:     Not Collective

271:     Input Parameter:
272: .   obj - the PETSc object

274:     Level: developer


277: .seealso: KSPSetFromOptions(), PCSetFromOptions(), SNESSetFromOptions(), PetscObjectAddOptionsHandler(), PetscObjectDestroyOptionsHandlers()

279: @*/
280: PetscErrorCode  PetscObjectProcessOptionsHandlers(PetscObject obj)
281: {
282:   PetscInt       i;

286:   for (i=0; i<obj->noptionhandler; i++) {
287:     (*obj->optionhandler[i])(obj,obj->optionctx[i]);
288:   }
289:   return(0);
290: }

294: /*@C
295:     PetscObjectDestroyOptionsHandlers - Destroys all the option handlers attached to an objeft

297:     Not Collective

299:     Input Parameter:
300: .   obj - the PETSc object

302:     Level: developer


305: .seealso: KSPSetFromOptions(), PCSetFromOptions(), SNESSetFromOptions(), PetscObjectAddOptionsHandler(), PetscObjectProcessOptionsHandlers()

307: @*/
308: PetscErrorCode  PetscObjectDestroyOptionsHandlers(PetscObject obj)
309: {
310:   PetscInt       i;

314:   for (i=0; i<obj->noptionhandler; i++) {
315:     (*obj->optiondestroy[i])(obj,obj->optionctx[i]);
316:   }
317:   obj->noptionhandler = 0;
318:   return(0);
319: }


324: /*@
325:    PetscObjectReference - Indicates to any PetscObject that it is being
326:    referenced by another PetscObject. This increases the reference
327:    count for that object by one.

329:    Logically Collective on PetscObject

331:    Input Parameter:
332: .  obj - the PETSc object. This must be cast with (PetscObject), for example, 
333:          PetscObjectReference((PetscObject)mat);

335:    Level: advanced

337: .seealso: PetscObjectCompose(), PetscObjectDereference()
338: @*/
339: PetscErrorCode  PetscObjectReference(PetscObject obj)
340: {
343:   obj->refct++;
344:   return(0);
345: }

349: /*@
350:    PetscObjectGetReference - Gets the current reference count for 
351:    any PETSc object.

353:    Not Collective

355:    Input Parameter:
356: .  obj - the PETSc object; this must be cast with (PetscObject), for example, 
357:          PetscObjectGetReference((PetscObject)mat,&cnt);

359:    Output Parameter:
360: .  cnt - the reference count

362:    Level: advanced

364: .seealso: PetscObjectCompose(), PetscObjectDereference(), PetscObjectReference()
365: @*/
366: PetscErrorCode  PetscObjectGetReference(PetscObject obj,PetscInt *cnt)
367: {
371:   *cnt = obj->refct;
372:   return(0);
373: }

377: /*@
378:    PetscObjectDereference - Indicates to any PetscObject that it is being
379:    referenced by one less PetscObject. This decreases the reference
380:    count for that object by one.

382:    Collective on PetscObject if reference reaches 0 otherwise Logically Collective

384:    Input Parameter:
385: .  obj - the PETSc object; this must be cast with (PetscObject), for example, 
386:          PetscObjectDereference((PetscObject)mat);

388:    Notes: PetscObjectDestroy(PetscObject *obj)  sets the obj pointer to null after the call, this routine does not.

390:    Level: advanced

392: .seealso: PetscObjectCompose(), PetscObjectReference()
393: @*/
394: PetscErrorCode  PetscObjectDereference(PetscObject obj)
395: {

400:   if (obj->bops->destroy) {
401:     (*obj->bops->destroy)(&obj);
402:   } else if (!--obj->refct) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"This PETSc object does not have a generic destroy routine");
403:   return(0);
404: }

406: /* ----------------------------------------------------------------------- */
407: /*
408:      The following routines are the versions private to the PETSc object
409:      data structures.
410: */
413: PetscErrorCode PetscObjectGetComm_Petsc(PetscObject obj,MPI_Comm *comm)
414: {
416:   *comm = obj->comm;
417:   return(0);
418: }

422: PetscErrorCode PetscObjectRemoveReference(PetscObject obj,const char name[])
423: {

427:   PetscOListRemoveReference(&obj->olist,name);
428:   return(0);
429: }

433: PetscErrorCode PetscObjectCompose_Petsc(PetscObject obj,const char name[],PetscObject ptr)
434: {
436:   char           *tname;
437:   PetscBool      skipreference;

440:   if (ptr) {
441:     PetscOListReverseFind(ptr->olist,obj,&tname,&skipreference);
442:     if (tname && !skipreference) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"An object cannot be composed with an object that was compose with it");
443:   }
444:   PetscOListAdd(&obj->olist,name,ptr);
445:   return(0);
446: }

450: PetscErrorCode PetscObjectQuery_Petsc(PetscObject obj,const char name[],PetscObject *ptr)
451: {

455:   PetscOListFind(obj->olist,name,ptr);
456:   return(0);
457: }

461: PetscErrorCode PetscObjectComposeFunction_Petsc(PetscObject obj,const char name[],const char fname[],void (*ptr)(void))
462: {

466:   PetscFListAdd(&obj->qlist,name,fname,ptr);
467:   return(0);
468: }

472: PetscErrorCode PetscObjectQueryFunction_Petsc(PetscObject obj,const char name[],void (**ptr)(void))
473: {

477:   PetscFListFind(obj->qlist,obj->comm,name,PETSC_FALSE,ptr);
478:   return(0);
479: }

483: /*@C
484:    PetscObjectCompose - Associates another PETSc object with a given PETSc object. 
485:                        
486:    Not Collective

488:    Input Parameters:
489: +  obj - the PETSc object; this must be cast with (PetscObject), for example, 
490:          PetscObjectCompose((PetscObject)mat,...);
491: .  name - name associated with the child object 
492: -  ptr - the other PETSc object to associate with the PETSc object; this must also be 
493:          cast with (PetscObject)

495:    Level: advanced

497:    Notes:
498:    The second objects reference count is automatically increased by one when it is
499:    composed.

501:    Replaces any previous object that had the same name.

503:    If ptr is null and name has previously been composed using an object, then that
504:    entry is removed from the obj.

506:    PetscObjectCompose() can be used with any PETSc object (such as
507:    Mat, Vec, KSP, SNES, etc.) or any user-provided object.  See 
508:    PetscContainerCreate() for info on how to create an object from a 
509:    user-provided pointer that may then be composed with PETSc objects.
510:    
511:    Concepts: objects^composing
512:    Concepts: composing objects

514: .seealso: PetscObjectQuery(), PetscContainerCreate()
515: @*/
516: PetscErrorCode  PetscObjectCompose(PetscObject obj,const char name[],PetscObject ptr)
517: {

524:   (*obj->bops->compose)(obj,name,ptr);
525:   return(0);
526: }

530: /*@C
531:    PetscObjectSetPrecision - sets the precision used within a given object.
532:                        
533:    Collective on the PetscObject

535:    Input Parameters:
536: +  obj - the PETSc object; this must be cast with (PetscObject), for example, 
537:          PetscObjectCompose((PetscObject)mat,...);
538: -  precision - the precision

540:    Level: advanced

542: .seealso: PetscObjectQuery(), PetscContainerCreate()
543: @*/
544: PetscErrorCode  PetscObjectSetPrecision(PetscObject obj,PetscPrecision precision)
545: {
548:   obj->precision = precision;
549:   return(0);
550: }

554: /*@C
555:    PetscObjectQuery  - Gets a PETSc object associated with a given object.
556:                        
557:    Not Collective

559:    Input Parameters:
560: +  obj - the PETSc object
561:          Thus must be cast with a (PetscObject), for example, 
562:          PetscObjectCompose((PetscObject)mat,...);
563: .  name - name associated with child object 
564: -  ptr - the other PETSc object associated with the PETSc object, this must be 
565:          cast with (PetscObject *)

567:    Level: advanced

569:    The reference count of neither object is increased in this call

571:    Concepts: objects^composing
572:    Concepts: composing objects
573:    Concepts: objects^querying
574:    Concepts: querying objects

576: .seealso: PetscObjectCompose()
577: @*/
578: PetscErrorCode  PetscObjectQuery(PetscObject obj,const char name[],PetscObject *ptr)
579: {

586:   (*obj->bops->query)(obj,name,ptr);
587:   return(0);
588: }

592: PetscErrorCode  PetscObjectComposeFunction(PetscObject obj,const char name[],const char fname[],void (*ptr)(void))
593: {

600:   (*obj->bops->composefunction)(obj,name,fname,ptr);
601:   return(0);
602: }

606: /*@C
607:    PetscObjectQueryFunction - Gets a function associated with a given object.
608:                        
609:    Logically Collective on PetscObject

611:    Input Parameters:
612: +  obj - the PETSc object; this must be cast with (PetscObject), for example, 
613:          PetscObjectQueryFunction((PetscObject)ksp,...);
614: -  name - name associated with the child function

616:    Output Parameter:
617: .  ptr - function pointer

619:    Level: advanced

621:    Concepts: objects^composing functions
622:    Concepts: composing functions
623:    Concepts: functions^querying
624:    Concepts: objects^querying
625:    Concepts: querying objects

627: .seealso: PetscObjectComposeFunctionDynamic()
628: @*/
629: PetscErrorCode  PetscObjectQueryFunction(PetscObject obj,const char name[],void (**ptr)(void))
630: {

636:   (*obj->bops->queryfunction)(obj,name,ptr);
637:   return(0);
638: }

640: struct _p_PetscContainer {
641:   PETSCHEADER(int);
642:   void   *ptr;
643:   PetscErrorCode (*userdestroy)(void*);
644: };

648: /*@C
649:    PetscContainerGetPointer - Gets the pointer value contained in the container.

651:    Not Collective

653:    Input Parameter:
654: .  obj - the object created with PetscContainerCreate()

656:    Output Parameter:
657: .  ptr - the pointer value

659:    Level: advanced

661: .seealso: PetscContainerCreate(), PetscContainerDestroy(), 
662:           PetscContainerSetPointer()
663: @*/
664: PetscErrorCode  PetscContainerGetPointer(PetscContainer obj,void **ptr)
665: {
669:   *ptr = obj->ptr;
670:   return(0);
671: }


676: /*@C
677:    PetscContainerSetPointer - Sets the pointer value contained in the container.

679:    Logically Collective on PetscContainer

681:    Input Parameters:
682: +  obj - the object created with PetscContainerCreate()
683: -  ptr - the pointer value

685:    Level: advanced

687: .seealso: PetscContainerCreate(), PetscContainerDestroy(), 
688:           PetscContainerGetPointer()
689: @*/
690: PetscErrorCode  PetscContainerSetPointer(PetscContainer obj,void *ptr)
691: {
695:   obj->ptr = ptr;
696:   return(0);
697: }

701: /*@C
702:    PetscContainerDestroy - Destroys a PETSc container object.

704:    Collective on PetscContainer

706:    Input Parameter:
707: .  obj - an object that was created with PetscContainerCreate()

709:    Level: advanced

711: .seealso: PetscContainerCreate(), PetscContainerSetUserDestroy()
712: @*/
713: PetscErrorCode  PetscContainerDestroy(PetscContainer *obj)
714: {
717:   if (!*obj) return(0);
719:   if (--((PetscObject)(*obj))->refct > 0) return(0);
720:   if ((*obj)->userdestroy) (*(*obj)->userdestroy)((*obj)->ptr);
721:   PetscHeaderDestroy(obj);
722:   return(0);
723: }

727: /*@C
728:    PetscContainerSetUserDestroy - Sets name of the user destroy function.

730:    Logically Collective on PetscContainer

732:    Input Parameter:
733: +  obj - an object that was created with PetscContainerCreate()
734: -  des - name of the user destroy function

736:    Level: advanced

738: .seealso: PetscContainerDestroy()
739: @*/
740: PetscErrorCode  PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void*))
741: {
744:   obj->userdestroy = des;
745:   return(0);
746: }

748: PetscClassId  PETSC_CONTAINER_CLASSID;

752: /*@C
753:    PetscContainerCreate - Creates a PETSc object that has room to hold
754:    a single pointer. This allows one to attach any type of data (accessible
755:    through a pointer) with the PetscObjectCompose() function to a PetscObject.
756:    The data item itself is attached by a call to PetscContainerSetPointer().

758:    Collective on MPI_Comm

760:    Input Parameters:
761: .  comm - MPI communicator that shares the object

763:    Output Parameters:
764: .  container - the container created

766:    Level: advanced

768: .seealso: PetscContainerDestroy(), PetscContainerSetPointer(), PetscContainerGetPointer()
769: @*/
770: PetscErrorCode  PetscContainerCreate(MPI_Comm comm,PetscContainer *container)
771: {
773:   PetscContainer contain;

777:   PetscHeaderCreate(contain,_p_PetscContainer,PetscInt,PETSC_CONTAINER_CLASSID,0,"PetscContainer","Container","Sys",comm,PetscContainerDestroy,0);
778:   *container = contain;
779:   return(0);
780: }

784: /*@
785:    PetscObjectSetFromOptions - Sets generic parameters from user options.

787:    Collective on obj

789:    Input Parameter:
790: .  obj - the PetscObjcet

792:    Options Database Keys:

794:    Notes:
795:    We have no generic options at present, so this does nothing

797:    Level: beginner

799: .keywords: set, options, database
800: .seealso: PetscObjectSetOptionsPrefix(), PetscObjectGetOptionsPrefix()
801: @*/
802: PetscErrorCode  PetscObjectSetFromOptions(PetscObject obj)
803: {
806:   return(0);
807: }

811: /*@
812:    PetscObjectSetUp - Sets up the internal data structures for the later use.

814:    Collective on PetscObject

816:    Input Parameters:
817: .  obj - the PetscObject

819:    Notes:
820:    This does nothing at present.

822:    Level: advanced

824: .keywords: setup
825: .seealso: PetscObjectDestroy()
826: @*/
827: PetscErrorCode  PetscObjectSetUp(PetscObject obj)
828: {
831:   return(0);
832: }