1*4bcd95a3SBarry Smith# Basic Object Design and Implementation 2*4bcd95a3SBarry Smith 3*4bcd95a3SBarry SmithPETSc is designed by using strong data encapsulation. Hence, any 4*4bcd95a3SBarry Smithcollection of data (for instance, a sparse matrix) is stored in a way 5*4bcd95a3SBarry Smiththat is completely private from the application code. The application 6*4bcd95a3SBarry Smithcode can manipulate the data only through a well-defined interface, 7*4bcd95a3SBarry Smithsince it does *not* "know" how the data is stored internally. 8*4bcd95a3SBarry Smith 9*4bcd95a3SBarry Smith## Introduction 10*4bcd95a3SBarry Smith 11*4bcd95a3SBarry SmithPETSc is designed around several classes including `Vec` (vectors) and 12*4bcd95a3SBarry Smith`Mat` (matrices, both dense and sparse). Each class is implemented by 13*4bcd95a3SBarry Smithusing a C `struct` that contains the data and function pointers for 14*4bcd95a3SBarry Smithoperations on the data (much like virtual functions in C++ classes). 15*4bcd95a3SBarry SmithEach class consists of three parts: 16*4bcd95a3SBarry Smith 17*4bcd95a3SBarry SmithA (small) common part shared by all PETSc classes (for example, both 18*4bcd95a3SBarry Smith`KSP` and `PC` have this same header). 19*4bcd95a3SBarry Smith 20*4bcd95a3SBarry SmithAnother common part shared by all PETSc implementations of the class 21*4bcd95a3SBarry Smith(for example, both `KSPGMRES` and `KSPCG` have this common 22*4bcd95a3SBarry Smithsubheader). 23*4bcd95a3SBarry Smith 24*4bcd95a3SBarry SmithA private part used by only one particular implementation written in 25*4bcd95a3SBarry SmithPETSc. 26*4bcd95a3SBarry Smith 27*4bcd95a3SBarry SmithFor example, all matrix (`Mat`) classes share a function table of 28*4bcd95a3SBarry Smithoperations that may be performed on the matrix; all PETSc matrix 29*4bcd95a3SBarry Smithimplementations share some additional data fields, including matrix 30*4bcd95a3SBarry Smithparallel layout, while a particular matrix implementation in PETSc (say 31*4bcd95a3SBarry Smithcompressed sparse row) has its own data fields for storing the actual 32*4bcd95a3SBarry Smithmatrix values and sparsity pattern. This will be explained in more 33*4bcd95a3SBarry Smithdetail in the following sections. New class implementations *must* use 34*4bcd95a3SBarry Smiththe PETSc common part. 35*4bcd95a3SBarry Smith 36*4bcd95a3SBarry SmithWe will use `<class>_<implementation>` to denote the actual source code 37*4bcd95a3SBarry Smithand data structures used for a particular implementation of an object 38*4bcd95a3SBarry Smiththat has the `<class>` interface. 39*4bcd95a3SBarry Smith 40*4bcd95a3SBarry Smith## Organization of the Source Code 41*4bcd95a3SBarry Smith 42*4bcd95a3SBarry SmithEach class has the following organization. 43*4bcd95a3SBarry Smith 44*4bcd95a3SBarry SmithIts own, application-public, include file `include/petsc<class>.h`. 45*4bcd95a3SBarry Smith 46*4bcd95a3SBarry SmithIts own directory, `src/<class>` or `src/<package>/<class>`. 47*4bcd95a3SBarry Smith 48*4bcd95a3SBarry SmithA data structure defined in the file 49*4bcd95a3SBarry Smith`include/petsc/private/<class>impl.h`. This data structure is shared 50*4bcd95a3SBarry Smithby all the different PETSc implementations of the class. For example, 51*4bcd95a3SBarry Smithfor matrices it is shared by dense, sparse, parallel, and sequential 52*4bcd95a3SBarry Smithformats. 53*4bcd95a3SBarry Smith 54*4bcd95a3SBarry SmithAn abstract interface that defines the application-callable functions 55*4bcd95a3SBarry Smithfor the class. These are defined in the directory 56*4bcd95a3SBarry Smith`src/<class>/interface`. This is how polymorphism is supported with 57*4bcd95a3SBarry Smithcode that implements the abstract interface to the operations on the 58*4bcd95a3SBarry Smithobject. Essentially, these routines do some error checking of arguments 59*4bcd95a3SBarry Smithand logging of profiling information and then call the function 60*4bcd95a3SBarry Smithappropriate for the particular implementation of the object. The name of 61*4bcd95a3SBarry Smiththe abstract function is `<class>Operation`, for instance, 62*4bcd95a3SBarry Smith`MatMult()` or `PCCreate(`), while the name of a particular 63*4bcd95a3SBarry Smithimplementation is `<class>Operation_<implementation>`, for instance, 64*4bcd95a3SBarry Smith`MatMult_SeqAIJ()` or `PCCreate_ILU()`. These naming conventions are 65*4bcd95a3SBarry Smithused to simplify code maintenance (also see Section [sec:stylenames]). 66*4bcd95a3SBarry Smith 67*4bcd95a3SBarry SmithOne or more actual implementations of the class (for example, sparse 68*4bcd95a3SBarry Smithuniprocessor and parallel matrices implemented with the AIJ storage 69*4bcd95a3SBarry Smithformat). These are each in a subdirectory of `src/<class>/impls`. 70*4bcd95a3SBarry SmithExcept in rare circumstances, data structures defined here should not be 71*4bcd95a3SBarry Smithreferenced from outside this directory. 72*4bcd95a3SBarry Smith 73*4bcd95a3SBarry SmithEach type of object (for instance, a vector) is defined in its own 74*4bcd95a3SBarry Smithpublic include file, by `typedef _p_<class>* <class>`; (for example, 75*4bcd95a3SBarry Smith`typedef _p_Vec* Vec;`). This organization allows the compiler to 76*4bcd95a3SBarry Smithperform type checking on all subroutine calls while at the same time 77*4bcd95a3SBarry Smithcompletely removing the details of the implementation of `_p_<class>` 78*4bcd95a3SBarry Smithfrom the application code. This capability is extremely important 79*4bcd95a3SBarry Smithbecause it allows the library internals to be changed without altering 80*4bcd95a3SBarry Smithor recompiling the application code. 81*4bcd95a3SBarry Smith 82*4bcd95a3SBarry Smith## Common Object Header 83*4bcd95a3SBarry Smith 84*4bcd95a3SBarry SmithAll PETSc objects (derived from the base class ``PetscObject``) have the following common header structures 85*4bcd95a3SBarry Smithdefined in 86*4bcd95a3SBarry Smith<a href="PETSC_DOC_OUT_ROOT_PLACEHOLDER/include/petsc/private/petscimpl.h.html">include/petsc/private/petscimpl.h</a> 87*4bcd95a3SBarry Smith 88*4bcd95a3SBarry Smith``` 89*4bcd95a3SBarry Smithtypedef struct { 90*4bcd95a3SBarry Smith PetscErrorCode (*getcomm)(PetscObject,MPI_Comm*); 91*4bcd95a3SBarry Smith PetscErrorCode (*view)(PetscObject,Viewer); 92*4bcd95a3SBarry Smith PetscErrorCode (*destroy)(PetscObject); 93*4bcd95a3SBarry Smith PetscErrorCode (*query)(PetscObject,const char*,PetscObject*); 94*4bcd95a3SBarry Smith PetscErrorCode (*compose)(PetscObject,const char*,PetscObject); 95*4bcd95a3SBarry Smith PetscErrorCode (*composefunction)(PetscObject,const char*,void(*)(void)); 96*4bcd95a3SBarry Smith PetscErrorCode (*queryfunction)(PetscObject,const char*,void (**)(void)); 97*4bcd95a3SBarry Smith} PetscOps; 98*4bcd95a3SBarry Smith``` 99*4bcd95a3SBarry Smith 100*4bcd95a3SBarry Smith``` 101*4bcd95a3SBarry Smithstruct _p_<class> { 102*4bcd95a3SBarry Smith PetscClassId classid; 103*4bcd95a3SBarry Smith PetscOps *bops; 104*4bcd95a3SBarry Smith <class>Ops *ops; 105*4bcd95a3SBarry Smith MPI_Comm comm; 106*4bcd95a3SBarry Smith PetscLogDouble flops,time,mem; 107*4bcd95a3SBarry Smith int id; 108*4bcd95a3SBarry Smith int refct; 109*4bcd95a3SBarry Smith int tag; 110*4bcd95a3SBarry Smith DLList qlist; 111*4bcd95a3SBarry Smith OList olist; 112*4bcd95a3SBarry Smith char *type_name; 113*4bcd95a3SBarry Smith PetscObject parent; 114*4bcd95a3SBarry Smith char *name; 115*4bcd95a3SBarry Smith char *prefix; 116*4bcd95a3SBarry Smith void *cpp; 117*4bcd95a3SBarry Smith void **fortran_func_pointers; 118*4bcd95a3SBarry Smith .......... 119*4bcd95a3SBarry Smith CLASS-SPECIFIC DATASTRUCTURES 120*4bcd95a3SBarry Smith}; 121*4bcd95a3SBarry Smith``` 122*4bcd95a3SBarry Smith 123*4bcd95a3SBarry SmithHere `<class>ops` is a function table (like the `PetscOps` above) 124*4bcd95a3SBarry Smiththat contains the function pointers for the operations specific to that 125*4bcd95a3SBarry Smithclass. For example, the PETSc vector class object operations in 126*4bcd95a3SBarry Smith<a href="PETSC_DOC_OUT_ROOT_PLACEHOLDER/include/petsc/private/vecimpl.h.html">include/petsc/private/vecimpl.h</a> 127*4bcd95a3SBarry Smithinclude the following. 128*4bcd95a3SBarry Smith 129*4bcd95a3SBarry Smith``` 130*4bcd95a3SBarry Smithtypedef struct _VecOps* VecOps; 131*4bcd95a3SBarry Smithstruct _VecOps { 132*4bcd95a3SBarry Smith PetscErrorCode (*duplicate)(Vec,Vec*); /* get single vector */ 133*4bcd95a3SBarry Smith PetscErrorCode (*duplicatevecs)(Vec,PetscInt,Vec**); /* get array of vectors */ 134*4bcd95a3SBarry Smith PetscErrorCode (*destroyvecs)(PetscInt,Vec[]); /* free array of vectors */ 135*4bcd95a3SBarry Smith PetscErrorCode (*dot)(Vec,Vec,PetscScalar*); /* z = x^H * y */ 136*4bcd95a3SBarry Smith PetscErrorCode (*mdot)(Vec,PetscInt,const Vec[],PetscScalar*); /* z[j] = x dot y[j] */ 137*4bcd95a3SBarry Smith PetscErrorCode (*norm)(Vec,NormType,PetscReal*); /* z = sqrt(x^H * x) */ 138*4bcd95a3SBarry Smith PetscErrorCode (*tdot)(Vec,Vec,PetscScalar*); /* x'*y */ 139*4bcd95a3SBarry Smith PetscErrorCode (*mtdot)(Vec,PetscInt,const Vec[],PetscScalar*);/* z[j] = x dot y[j] */ 140*4bcd95a3SBarry Smith PetscErrorCode (*scale)(Vec,PetscScalar); /* x = alpha * x */ 141*4bcd95a3SBarry Smith PetscErrorCode (*copy)(Vec,Vec); /* y = x */ 142*4bcd95a3SBarry Smith PetscErrorCode (*set)(Vec,PetscScalar); /* y = alpha */ 143*4bcd95a3SBarry Smith PetscErrorCode (*swap)(Vec,Vec); /* exchange x and y */ 144*4bcd95a3SBarry Smith PetscErrorCode (*axpy)(Vec,PetscScalar,Vec); /* y = y + alpha * x */ 145*4bcd95a3SBarry Smith PetscErrorCode (*axpby)(Vec,PetscScalar,PetscScalar,Vec); /* y = alpha * x + beta * y*/ 146*4bcd95a3SBarry Smith PetscErrorCode (*maxpy)(Vec,PetscInt,const PetscScalar*,Vec*); /* y = y + alpha[j] x[j] */ 147*4bcd95a3SBarry Smith ... (AND SO ON) ... 148*4bcd95a3SBarry Smith}; 149*4bcd95a3SBarry Smith``` 150*4bcd95a3SBarry Smith 151*4bcd95a3SBarry Smith``` 152*4bcd95a3SBarry Smithstruct _p_Vec { 153*4bcd95a3SBarry Smith PetscClassId classid; 154*4bcd95a3SBarry Smith PetscOps *bops; 155*4bcd95a3SBarry Smith VecOps *ops; 156*4bcd95a3SBarry Smith MPI_Comm comm; 157*4bcd95a3SBarry Smith PetscLogDouble flops,time,mem; 158*4bcd95a3SBarry Smith int id; 159*4bcd95a3SBarry Smith int refct; 160*4bcd95a3SBarry Smith int tag; 161*4bcd95a3SBarry Smith DLList qlist; 162*4bcd95a3SBarry Smith OList olist; 163*4bcd95a3SBarry Smith char *type_name; 164*4bcd95a3SBarry Smith PetscObject parent; 165*4bcd95a3SBarry Smith char *name; 166*4bcd95a3SBarry Smith char *prefix; 167*4bcd95a3SBarry Smith void **fortran_func_pointers; 168*4bcd95a3SBarry Smith void *data; /* implementation-specific data */ 169*4bcd95a3SBarry Smith PetscLayout map; 170*4bcd95a3SBarry Smith ISLocalToGlobalMapping mapping; /* mapping used in VecSetValuesLocal() */ 171*4bcd95a3SBarry Smith}; 172*4bcd95a3SBarry Smith``` 173*4bcd95a3SBarry Smith 174*4bcd95a3SBarry SmithEach PETSc object begins with a `PetscClassId`, which is used for 175*4bcd95a3SBarry Smitherror checking. Each different class of objects has its value for 176*4bcd95a3SBarry Smith`classid`; these are used to distinguish between classes. When a new 177*4bcd95a3SBarry Smithclass is created you need to call 178*4bcd95a3SBarry Smith 179*4bcd95a3SBarry Smith``` 180*4bcd95a3SBarry SmithPetscClassIdRegister(const char *classname,PetscClassId *classid); 181*4bcd95a3SBarry Smith``` 182*4bcd95a3SBarry Smith 183*4bcd95a3SBarry SmithFor example, 184*4bcd95a3SBarry Smith 185*4bcd95a3SBarry Smith``` 186*4bcd95a3SBarry SmithPetscClassIdRegister("index set",&IS_CLASSID); 187*4bcd95a3SBarry Smith``` 188*4bcd95a3SBarry Smith 189*4bcd95a3SBarry Smithyou can verify that an object is valid of a particular class with 190*4bcd95a3SBarry Smith`PetscValidHeaderSpecific`, for example, 191*4bcd95a3SBarry Smith 192*4bcd95a3SBarry Smith``` 193*4bcd95a3SBarry SmithPetscValidHeaderSpecific(x,VEC_CLASSID,1); 194*4bcd95a3SBarry Smith``` 195*4bcd95a3SBarry Smith 196*4bcd95a3SBarry SmithThe third argument to this macro indicates the position in the calling 197*4bcd95a3SBarry Smithsequence of the function the object was passed in. This is to generate 198*4bcd95a3SBarry Smithmore complete error messages. 199*4bcd95a3SBarry Smith 200*4bcd95a3SBarry SmithTo check for an object of any type, use 201*4bcd95a3SBarry Smith 202*4bcd95a3SBarry Smith``` 203*4bcd95a3SBarry SmithPetscValidHeader(x,1); 204*4bcd95a3SBarry Smith``` 205*4bcd95a3SBarry Smith 206*4bcd95a3SBarry SmithThe `obj->ops` functions provide implementations of the standard methods of the object class. Each type 207*4bcd95a3SBarry Smithof the class may have different function pointers in the array. Subtypes sometimes replace some of the 208*4bcd95a3SBarry Smithfunction pointers of the parent, so they play the role of virtual methods in C++. 209*4bcd95a3SBarry Smith 210*4bcd95a3SBarry SmithPETSc code that calls these function pointers should be done via 211*4bcd95a3SBarry Smith 212*4bcd95a3SBarry Smith``` 213*4bcd95a3SBarry SmithPetscUseTypeMethod(obj,method,other arguments); 214*4bcd95a3SBarry SmithPetscTryTypeMethod(obj,method,other arguments); 215*4bcd95a3SBarry Smith``` 216*4bcd95a3SBarry Smith 217*4bcd95a3SBarry SmithFor example, 218*4bcd95a3SBarry Smith 219*4bcd95a3SBarry Smith``` 220*4bcd95a3SBarry SmithPetscErrorCode XXXOp(XXX x,YYY y) 221*4bcd95a3SBarry Smith{ 222*4bcd95a3SBarry Smith PetscFunctionBegin; 223*4bcd95a3SBarry Smith PetscUseTypeMethod(x,op,y); 224*4bcd95a3SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 225*4bcd95a3SBarry Smith} 226*4bcd95a3SBarry Smith``` 227*4bcd95a3SBarry Smith 228*4bcd95a3SBarry SmithThe `Try` variant skips the function call if the method has not been set while the `Use` version generates an error in that case. 229*4bcd95a3SBarry Smith 230*4bcd95a3SBarry SmithSee also, `PetscUseMethod()`, and `PetscTryMethod()`. 231*4bcd95a3SBarry Smith 232*4bcd95a3SBarry Smith## Common Object Functions 233*4bcd95a3SBarry Smith 234*4bcd95a3SBarry SmithSeveral routines are provided for manipulating data within the header. 235*4bcd95a3SBarry SmithThese include the specific functions in the PETSc common function table. 236*4bcd95a3SBarry SmithThe function pointers are not called directly; rather you should call 237*4bcd95a3SBarry Smith`PetscObjectFunctionName()`, where `FunctionName` is one of the 238*4bcd95a3SBarry Smithfunctions listed below with the first letter of each word capitalized. 239*4bcd95a3SBarry Smith 240*4bcd95a3SBarry Smith``PetscObjectGetComm()`` calls the ``getcomm(PetscObject,MPI_Comm*)`` function point which obtains the MPI communicator 241*4bcd95a3SBarry Smithassociated with this object. 242*4bcd95a3SBarry Smith 243*4bcd95a3SBarry Smith``PetscObjectView()`` calls the ``view(PetscObject,PetscViewer)`` function point which allows you to store or visualize the 244*4bcd95a3SBarry Smithdata inside an object. If the ``PetscViewer`` is ``NULL``, then it should cause the 245*4bcd95a3SBarry Smithobject to print information on the object to ``stdout``. 246*4bcd95a3SBarry Smith 247*4bcd95a3SBarry Smith``PetscObjectDestroy()`` calls the ``destroy(PetscObject)`` function pointer which causes the reference count of the object to be 248*4bcd95a3SBarry Smithdecreased by one or the object to be destroyed and all memory used by 249*4bcd95a3SBarry Smiththe object to be freed when the reference count drops to zero. If the 250*4bcd95a3SBarry Smithobject has any other objects composed with it, the ``PetscObjectDestroy()`` function is called on them. 251*4bcd95a3SBarry Smith 252*4bcd95a3SBarry Smith``PetscObjectCompose()`` calls the ``compose(PetscObject,const char *name,PetscObject)`` function pointer which associates the 253*4bcd95a3SBarry Smithsecond object with the first object and increases the reference count of 254*4bcd95a3SBarry Smiththe second object. If an object with the same name was previously 255*4bcd95a3SBarry Smithcomposed, that object is dereferenced and replaced with the new object. 256*4bcd95a3SBarry SmithIf the second object is ``NULL`` and an object with the same name has 257*4bcd95a3SBarry Smithalready been composed, that object is dereferenced (the ``PetscObjectDestroy()`` 258*4bcd95a3SBarry Smithfunction is called on it, and that object is removed from the first 259*4bcd95a3SBarry Smithobject). This is a way to remove, by name, an object that was previously 260*4bcd95a3SBarry Smithcomposed. 261*4bcd95a3SBarry Smith 262*4bcd95a3SBarry Smith``PetscObjectQuery()`` calls the ``query(PetscObject,const char *name,PetscObject*)`` function pointer which retrieves an object 263*4bcd95a3SBarry Smiththat was previously composed with the first object via 264*4bcd95a3SBarry Smith``PetscObjectCompose()``. It retrieves a ``NULL`` if no object with that 265*4bcd95a3SBarry Smithname was previously composed. 266*4bcd95a3SBarry Smith 267*4bcd95a3SBarry Smith``PetscObjectComposeFunction()`` calls the ``composefunction(PetscObject,const char *name,void *func)`` function pointer which associates 268*4bcd95a3SBarry Smitha function pointer with an object. If the object already had a composed 269*4bcd95a3SBarry Smithfunction with the same name, the old one is replaced. If `func` is 270*4bcd95a3SBarry Smith`NULL`, the existing function is removed from the object. The string 271*4bcd95a3SBarry Smith`name` is the character string name of the function. 272*4bcd95a3SBarry Smith 273*4bcd95a3SBarry SmithFor example, `fname` may be `PCCreate_LU`. 274*4bcd95a3SBarry Smith 275*4bcd95a3SBarry Smith``PetscObjectQueryFunction()`` calls the ```queryfunction(PetscObject,const char *name,void **func)`` function pointer which retrieves a 276*4bcd95a3SBarry Smithfunction pointer that was associated with the object via 277*4bcd95a3SBarry Smith`PetscObjectComposeFunction()`. If dynamic libraries are used, the 278*4bcd95a3SBarry Smithfunction is loaded into memory at this time (if it has not been 279*4bcd95a3SBarry Smithpreviously loaded), not when the ``PetscObjectComposeFunction()`` routine was 280*4bcd95a3SBarry Smithcalled. 281*4bcd95a3SBarry Smith 282*4bcd95a3SBarry SmithSince the object composition allows one to compose PETSc objects 283*4bcd95a3SBarry Smithwith PETSc objects, PETSc provides the 284*4bcd95a3SBarry Smithconvenience object `PetscContainer`, created with the routine 285*4bcd95a3SBarry Smith`PetscContainerCreate(MPI_Comm,PetscContainer*)`, to allow wrapping any 286*4bcd95a3SBarry Smithkind of data into a PETSc object that can then be composed with a PETSc 287*4bcd95a3SBarry Smithobject. One can also use ``PetscObjectContainerCompose()`` and ``PetscObjectContainerQuery()`` to compose 288*4bcd95a3SBarry Smitharbitrary pointers with a PETSc object. 289*4bcd95a3SBarry Smith 290*4bcd95a3SBarry Smith## Object Function Implementation 291*4bcd95a3SBarry Smith 292*4bcd95a3SBarry SmithThis section discusses how PETSc implements the `compose()`, 293*4bcd95a3SBarry Smith`query()`, `composefunction()`, and `queryfunction()` functions 294*4bcd95a3SBarry Smithfor its object implementations. Other PETSc-compatible class 295*4bcd95a3SBarry Smithimplementations are free to manage these functions in any manner; but 296*4bcd95a3SBarry Smithunless there is a specific reason, they should use the PETSc defaults so 297*4bcd95a3SBarry Smiththat the library writer does not have to “reinvent the wheel.” 298*4bcd95a3SBarry Smith 299*4bcd95a3SBarry Smith### Compose and Query Objects 300*4bcd95a3SBarry Smith 301*4bcd95a3SBarry SmithIn 302*4bcd95a3SBarry Smith<a href="PETSC_DOC_OUT_ROOT_PLACEHOLDER/src/sys/objects/olist.c.html">src/sys/objects/olist.c</a> 303*4bcd95a3SBarry SmithPETSc defines a C `struct` 304*4bcd95a3SBarry Smith 305*4bcd95a3SBarry Smith``` 306*4bcd95a3SBarry Smithtypedef struct _PetscObjectList* PetscObjectList; 307*4bcd95a3SBarry Smithstruct _PetscObjectList { 308*4bcd95a3SBarry Smith char name[128]; 309*4bcd95a3SBarry Smith PetscObject obj; 310*4bcd95a3SBarry Smith PetscObjectList next; 311*4bcd95a3SBarry Smith}; 312*4bcd95a3SBarry Smith``` 313*4bcd95a3SBarry Smith 314*4bcd95a3SBarry Smithfrom which linked lists of composed objects may be constructed. The 315*4bcd95a3SBarry Smithroutines to manipulate these elementary objects are 316*4bcd95a3SBarry Smith 317*4bcd95a3SBarry Smith``` 318*4bcd95a3SBarry Smithint PetscObjectListAdd(PetscObjectList *fl,const char *name,PetscObject obj); 319*4bcd95a3SBarry Smithint PetscObjectListDestroy(PetscObjectList *fl); 320*4bcd95a3SBarry Smithint PetscObjectListFind(PetscObjectList fl,const char *name,PetscObject *obj) 321*4bcd95a3SBarry Smithint PetscObjectListDuplicate(PetscObjectList fl,PetscObjectList *nl); 322*4bcd95a3SBarry Smith``` 323*4bcd95a3SBarry Smith 324*4bcd95a3SBarry SmithThe function `PetscObjectListAdd()` will create the initial 325*4bcd95a3SBarry SmithPetscObjectList if the argument `fl` points to a NULL. 326*4bcd95a3SBarry Smith 327*4bcd95a3SBarry SmithThe PETSc object `compose()` and `query()` functions are as follows 328*4bcd95a3SBarry Smith(defined in 329*4bcd95a3SBarry Smith<a href="PETSC_DOC_OUT_ROOT_PLACEHOLDER/src/sys/objects/inherit.c.html">src/sys/objects/inherit.c</a> 330*4bcd95a3SBarry Smith 331*4bcd95a3SBarry Smith``` 332*4bcd95a3SBarry SmithPetscErrorCode PetscObjectCompose_Petsc(PetscObject obj,const char *name,PetscObject ptr) 333*4bcd95a3SBarry Smith{ 334*4bcd95a3SBarry Smith PetscFunctionBegin; 335*4bcd95a3SBarry Smith PetscCall(PetscObjectListAdd(&obj->olist,name,ptr)); 336*4bcd95a3SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 337*4bcd95a3SBarry Smith} 338*4bcd95a3SBarry Smith 339*4bcd95a3SBarry SmithPetscErrorCode PetscObjectQuery_Petsc(PetscObject obj,const char *name,PetscObject *ptr) 340*4bcd95a3SBarry Smith{ 341*4bcd95a3SBarry Smith PetscFunctionBegin; 342*4bcd95a3SBarry Smith PetscCall(PetscObjectListFind(obj->olist,name,ptr)); 343*4bcd95a3SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 344*4bcd95a3SBarry Smith} 345*4bcd95a3SBarry Smith``` 346*4bcd95a3SBarry Smith 347*4bcd95a3SBarry Smith### Compose and Query Functions 348*4bcd95a3SBarry Smith 349*4bcd95a3SBarry SmithPETSc allows you to compose functions by specifying a name and function 350*4bcd95a3SBarry Smithpointer. In 351*4bcd95a3SBarry Smith<a href="PETSC_DOC_OUT_ROOT_PLACEHOLDER/src/sys/dll/reg.c.html">src/sys/dll/reg.c</a> 352*4bcd95a3SBarry SmithPETSc defines the following linked list structure. 353*4bcd95a3SBarry Smith 354*4bcd95a3SBarry Smith``` 355*4bcd95a3SBarry Smithstruct _n_PetscFunctionList { 356*4bcd95a3SBarry Smith void (*routine)(void); /* the routine */ 357*4bcd95a3SBarry Smith char *name; /* string to identify routine */ 358*4bcd95a3SBarry Smith PetscFunctionList next; /* next pointer */ 359*4bcd95a3SBarry Smith PetscFunctionList next_list; /* used to maintain list of all lists for freeing */ 360*4bcd95a3SBarry Smith}; 361*4bcd95a3SBarry Smith``` 362*4bcd95a3SBarry Smith 363*4bcd95a3SBarry SmithEach PETSc object contains a `PetscFunctionList` object. The 364*4bcd95a3SBarry Smith`composefunction()` and `queryfunction()` are given by the 365*4bcd95a3SBarry Smithfollowing. 366*4bcd95a3SBarry Smith 367*4bcd95a3SBarry Smith``` 368*4bcd95a3SBarry SmithPetscErrorCode PetscObjectComposeFunction_Petsc(PetscObject obj,const char *name,void *ptr) 369*4bcd95a3SBarry Smith{ 370*4bcd95a3SBarry Smith PetscFunctionBegin; 371*4bcd95a3SBarry Smith PetscCall(PetscFunctionListAdd(&obj->qlist,name,fname,ptr)); 372*4bcd95a3SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 373*4bcd95a3SBarry Smith} 374*4bcd95a3SBarry Smith 375*4bcd95a3SBarry SmithPetscErrorCode PetscObjectQueryFunction_Petsc(PetscObject obj,const char *name,void (**ptr)(void)) 376*4bcd95a3SBarry Smith{ 377*4bcd95a3SBarry Smith PetscFunctionBegin; 378*4bcd95a3SBarry Smith PetscCall(PetscFunctionListFind(obj->qlist,name,ptr)); 379*4bcd95a3SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 380*4bcd95a3SBarry Smith} 381*4bcd95a3SBarry Smith``` 382*4bcd95a3SBarry Smith 383*4bcd95a3SBarry SmithIn addition to using the `PetscFunctionList` mechanism to compose 384*4bcd95a3SBarry Smithfunctions into PETSc objects, it is also used to allow registration of 385*4bcd95a3SBarry Smithnew class implementations; for example, new preconditioners. 386*4bcd95a3SBarry Smith 387*4bcd95a3SBarry SmithPETSc code that calls composed functions should be done via 388*4bcd95a3SBarry Smith 389*4bcd95a3SBarry Smith``` 390*4bcd95a3SBarry SmithPetscUseMethod(obj,"method",(Argument types),(argument variables)); 391*4bcd95a3SBarry SmithPetscTryMethod(obj,"method",(Argument types),(argument variables)); 392*4bcd95a3SBarry Smith``` 393*4bcd95a3SBarry Smith 394*4bcd95a3SBarry SmithFor example, 395*4bcd95a3SBarry Smith 396*4bcd95a3SBarry Smith``` 397*4bcd95a3SBarry SmithPetscErrorCode KSPGMRESSetRestart(KSP ksp, PetscInt restart) 398*4bcd95a3SBarry Smith{ 399*4bcd95a3SBarry Smith PetscFunctionBegin; 400*4bcd95a3SBarry Smith PetscValidLogicalCollectiveInt(ksp,restart,2); 401*4bcd95a3SBarry Smith 402*4bcd95a3SBarry Smith PetscTryMethod(ksp,"KSPGMRESSetRestart_C",(KSP,PetscInt),(ksp,restart)); 403*4bcd95a3SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 404*4bcd95a3SBarry Smith} 405*4bcd95a3SBarry Smith``` 406*4bcd95a3SBarry Smith 407*4bcd95a3SBarry SmithThe `Try` variant skips the function call if the method has not been composed with 408*4bcd95a3SBarry Smiththe object while the `Use` version generates an error in that case. 409*4bcd95a3SBarry SmithSee also, `PetscUseTypeMethod()`, and `PetscTryTypeMethod()`. 410*4bcd95a3SBarry Smith 411*4bcd95a3SBarry Smith### Simple PETSc Objects 412*4bcd95a3SBarry Smith 413*4bcd95a3SBarry SmithSome simple PETSc objects do not need `PETSCHEADER` and the associated 414*4bcd95a3SBarry Smithfunctionality. These objects are internally named as `_n_<class>` as 415*4bcd95a3SBarry Smithopposed to `_p_<class>`, for example, `_n_PetscFunctionList` vs `_p_Vec`. 416*4bcd95a3SBarry Smith 417*4bcd95a3SBarry Smith## PETSc Packages 418*4bcd95a3SBarry Smith 419*4bcd95a3SBarry SmithThe PETSc source code is divided into the following library-level 420*4bcd95a3SBarry Smithpackages: `Sys`, `Vec`, `Mat`, `DM`, `KSP`, `SNES`, `TS`, 421*4bcd95a3SBarry Smith`Tao`. Each of these has a directory under the `src` directory in 422*4bcd95a3SBarry Smiththe PETSc tree and, optionally, can be compiled into separate libraries. 423*4bcd95a3SBarry SmithEach package defines one or more classes; for example, the `KSP` 424*4bcd95a3SBarry Smithpackage defines the `KSP` and `PC` classes, as well as several 425*4bcd95a3SBarry Smithutility classes. In addition, each library-level package may contain 426*4bcd95a3SBarry Smithseveral class-level packages associated with individual classes in the 427*4bcd95a3SBarry Smithlibrary-level package. In general, most “important” classes in PETSc 428*4bcd95a3SBarry Smithhave their own class level package. Each package provides a registration 429*4bcd95a3SBarry Smithfunction `XXXInitializePackage()`, for example 430*4bcd95a3SBarry Smith`KSPInitializePackage()`, which registers all the classes and events 431*4bcd95a3SBarry Smithfor that package. Each package also registers a finalization routine, 432*4bcd95a3SBarry Smith`XXXFinalizePackage()`, that releases all the resources used in 433*4bcd95a3SBarry Smithregistering the package, using `PetscRegisterFinalize()`. The 434*4bcd95a3SBarry Smithregistration for each package is performed “on demand” the first time a 435*4bcd95a3SBarry Smithclass in the package is utilized. This is handled, for example, with 436*4bcd95a3SBarry Smithcode such as 437*4bcd95a3SBarry Smith 438*4bcd95a3SBarry Smith``` 439*4bcd95a3SBarry SmithPetscErrorCode VecCreate(MPI_Comm comm, Vec *vec) 440*4bcd95a3SBarry Smith{ 441*4bcd95a3SBarry Smith Vec v; 442*4bcd95a3SBarry Smith 443*4bcd95a3SBarry Smith PetscFunctionBegin; 444*4bcd95a3SBarry Smith PetscAssertPointer(vec,2); 445*4bcd95a3SBarry Smith *vec = NULL; 446*4bcd95a3SBarry Smith VecInitializePackage(); 447*4bcd95a3SBarry Smith ... 448*4bcd95a3SBarry Smith``` 449