14bcd95a3SBarry Smith# Basic Object Design and Implementation 24bcd95a3SBarry Smith 34bcd95a3SBarry SmithPETSc is designed by using strong data encapsulation. Hence, any 44bcd95a3SBarry Smithcollection of data (for instance, a sparse matrix) is stored in a way 54bcd95a3SBarry Smiththat is completely private from the application code. The application 64bcd95a3SBarry Smithcode can manipulate the data only through a well-defined interface, 74bcd95a3SBarry Smithsince it does *not* "know" how the data is stored internally. 84bcd95a3SBarry Smith 94bcd95a3SBarry Smith## Introduction 104bcd95a3SBarry Smith 114bcd95a3SBarry SmithPETSc is designed around several classes including `Vec` (vectors) and 124bcd95a3SBarry Smith`Mat` (matrices, both dense and sparse). Each class is implemented by 134bcd95a3SBarry Smithusing a C `struct` that contains the data and function pointers for 144bcd95a3SBarry Smithoperations on the data (much like virtual functions in C++ classes). 154bcd95a3SBarry SmithEach class consists of three parts: 164bcd95a3SBarry Smith 174bcd95a3SBarry SmithA (small) common part shared by all PETSc classes (for example, both 184bcd95a3SBarry Smith`KSP` and `PC` have this same header). 194bcd95a3SBarry Smith 204bcd95a3SBarry SmithAnother common part shared by all PETSc implementations of the class 214bcd95a3SBarry Smith(for example, both `KSPGMRES` and `KSPCG` have this common 224bcd95a3SBarry Smithsubheader). 234bcd95a3SBarry Smith 244bcd95a3SBarry SmithA private part used by only one particular implementation written in 254bcd95a3SBarry SmithPETSc. 264bcd95a3SBarry Smith 274bcd95a3SBarry SmithFor example, all matrix (`Mat`) classes share a function table of 284bcd95a3SBarry Smithoperations that may be performed on the matrix; all PETSc matrix 294bcd95a3SBarry Smithimplementations share some additional data fields, including matrix 304bcd95a3SBarry Smithparallel layout, while a particular matrix implementation in PETSc (say 314bcd95a3SBarry Smithcompressed sparse row) has its own data fields for storing the actual 324bcd95a3SBarry Smithmatrix values and sparsity pattern. This will be explained in more 334bcd95a3SBarry Smithdetail in the following sections. New class implementations *must* use 344bcd95a3SBarry Smiththe PETSc common part. 354bcd95a3SBarry Smith 364bcd95a3SBarry SmithWe will use `<class>_<implementation>` to denote the actual source code 374bcd95a3SBarry Smithand data structures used for a particular implementation of an object 384bcd95a3SBarry Smiththat has the `<class>` interface. 394bcd95a3SBarry Smith 404bcd95a3SBarry Smith## Organization of the Source Code 414bcd95a3SBarry Smith 424bcd95a3SBarry SmithEach class has the following organization. 434bcd95a3SBarry Smith 444bcd95a3SBarry SmithIts own, application-public, include file `include/petsc<class>.h`. 454bcd95a3SBarry Smith 464bcd95a3SBarry SmithIts own directory, `src/<class>` or `src/<package>/<class>`. 474bcd95a3SBarry Smith 484bcd95a3SBarry SmithA data structure defined in the file 494bcd95a3SBarry Smith`include/petsc/private/<class>impl.h`. This data structure is shared 504bcd95a3SBarry Smithby all the different PETSc implementations of the class. For example, 514bcd95a3SBarry Smithfor matrices it is shared by dense, sparse, parallel, and sequential 524bcd95a3SBarry Smithformats. 534bcd95a3SBarry Smith 544bcd95a3SBarry SmithAn abstract interface that defines the application-callable functions 554bcd95a3SBarry Smithfor the class. These are defined in the directory 564bcd95a3SBarry Smith`src/<class>/interface`. This is how polymorphism is supported with 574bcd95a3SBarry Smithcode that implements the abstract interface to the operations on the 584bcd95a3SBarry Smithobject. Essentially, these routines do some error checking of arguments 594bcd95a3SBarry Smithand logging of profiling information and then call the function 604bcd95a3SBarry Smithappropriate for the particular implementation of the object. The name of 614bcd95a3SBarry Smiththe abstract function is `<class>Operation`, for instance, 624bcd95a3SBarry Smith`MatMult()` or `PCCreate(`), while the name of a particular 634bcd95a3SBarry Smithimplementation is `<class>Operation_<implementation>`, for instance, 644bcd95a3SBarry Smith`MatMult_SeqAIJ()` or `PCCreate_ILU()`. These naming conventions are 654bcd95a3SBarry Smithused to simplify code maintenance (also see Section [sec:stylenames]). 664bcd95a3SBarry Smith 674bcd95a3SBarry SmithOne or more actual implementations of the class (for example, sparse 684bcd95a3SBarry Smithuniprocessor and parallel matrices implemented with the AIJ storage 694bcd95a3SBarry Smithformat). These are each in a subdirectory of `src/<class>/impls`. 704bcd95a3SBarry SmithExcept in rare circumstances, data structures defined here should not be 714bcd95a3SBarry Smithreferenced from outside this directory. 724bcd95a3SBarry Smith 734bcd95a3SBarry SmithEach type of object (for instance, a vector) is defined in its own 744bcd95a3SBarry Smithpublic include file, by `typedef _p_<class>* <class>`; (for example, 754bcd95a3SBarry Smith`typedef _p_Vec* Vec;`). This organization allows the compiler to 764bcd95a3SBarry Smithperform type checking on all subroutine calls while at the same time 774bcd95a3SBarry Smithcompletely removing the details of the implementation of `_p_<class>` 784bcd95a3SBarry Smithfrom the application code. This capability is extremely important 794bcd95a3SBarry Smithbecause it allows the library internals to be changed without altering 804bcd95a3SBarry Smithor recompiling the application code. 814bcd95a3SBarry Smith 824bcd95a3SBarry Smith## Common Object Header 834bcd95a3SBarry Smith 84*7f296bb3SBarry SmithAll PETSc objects (derived from the base class `PetscObject`) have the following common header structures 854bcd95a3SBarry Smithdefined in 864bcd95a3SBarry Smith<a href="PETSC_DOC_OUT_ROOT_PLACEHOLDER/include/petsc/private/petscimpl.h.html">include/petsc/private/petscimpl.h</a> 874bcd95a3SBarry Smith 884bcd95a3SBarry Smith``` 894bcd95a3SBarry Smithtypedef struct { 904bcd95a3SBarry Smith PetscErrorCode (*getcomm)(PetscObject,MPI_Comm*); 914bcd95a3SBarry Smith PetscErrorCode (*view)(PetscObject,Viewer); 924bcd95a3SBarry Smith PetscErrorCode (*destroy)(PetscObject); 934bcd95a3SBarry Smith PetscErrorCode (*query)(PetscObject,const char*,PetscObject*); 944bcd95a3SBarry Smith PetscErrorCode (*compose)(PetscObject,const char*,PetscObject); 954bcd95a3SBarry Smith PetscErrorCode (*composefunction)(PetscObject,const char*,void(*)(void)); 964bcd95a3SBarry Smith PetscErrorCode (*queryfunction)(PetscObject,const char*,void (**)(void)); 974bcd95a3SBarry Smith} PetscOps; 984bcd95a3SBarry Smith``` 994bcd95a3SBarry Smith 1004bcd95a3SBarry Smith``` 1014bcd95a3SBarry Smithstruct _p_<class> { 1024bcd95a3SBarry Smith PetscClassId classid; 1034bcd95a3SBarry Smith PetscOps *bops; 1044bcd95a3SBarry Smith <class>Ops *ops; 1054bcd95a3SBarry Smith MPI_Comm comm; 1064bcd95a3SBarry Smith PetscLogDouble flops,time,mem; 1074bcd95a3SBarry Smith int id; 1084bcd95a3SBarry Smith int refct; 1094bcd95a3SBarry Smith int tag; 1104bcd95a3SBarry Smith DLList qlist; 1114bcd95a3SBarry Smith OList olist; 1124bcd95a3SBarry Smith char *type_name; 1134bcd95a3SBarry Smith PetscObject parent; 1144bcd95a3SBarry Smith char *name; 1154bcd95a3SBarry Smith char *prefix; 1164bcd95a3SBarry Smith void *cpp; 1174bcd95a3SBarry Smith void **fortran_func_pointers; 1184bcd95a3SBarry Smith .......... 1194bcd95a3SBarry Smith CLASS-SPECIFIC DATASTRUCTURES 1204bcd95a3SBarry Smith}; 1214bcd95a3SBarry Smith``` 1224bcd95a3SBarry Smith 1234bcd95a3SBarry SmithHere `<class>ops` is a function table (like the `PetscOps` above) 1244bcd95a3SBarry Smiththat contains the function pointers for the operations specific to that 1254bcd95a3SBarry Smithclass. For example, the PETSc vector class object operations in 1264bcd95a3SBarry Smith<a href="PETSC_DOC_OUT_ROOT_PLACEHOLDER/include/petsc/private/vecimpl.h.html">include/petsc/private/vecimpl.h</a> 1274bcd95a3SBarry Smithinclude the following. 1284bcd95a3SBarry Smith 1294bcd95a3SBarry Smith``` 1304bcd95a3SBarry Smithtypedef struct _VecOps* VecOps; 1314bcd95a3SBarry Smithstruct _VecOps { 1324bcd95a3SBarry Smith PetscErrorCode (*duplicate)(Vec,Vec*); /* get single vector */ 1334bcd95a3SBarry Smith PetscErrorCode (*duplicatevecs)(Vec,PetscInt,Vec**); /* get array of vectors */ 1344bcd95a3SBarry Smith PetscErrorCode (*destroyvecs)(PetscInt,Vec[]); /* free array of vectors */ 1354bcd95a3SBarry Smith PetscErrorCode (*dot)(Vec,Vec,PetscScalar*); /* z = x^H * y */ 1364bcd95a3SBarry Smith PetscErrorCode (*mdot)(Vec,PetscInt,const Vec[],PetscScalar*); /* z[j] = x dot y[j] */ 1374bcd95a3SBarry Smith PetscErrorCode (*norm)(Vec,NormType,PetscReal*); /* z = sqrt(x^H * x) */ 1384bcd95a3SBarry Smith PetscErrorCode (*tdot)(Vec,Vec,PetscScalar*); /* x'*y */ 1394bcd95a3SBarry Smith PetscErrorCode (*mtdot)(Vec,PetscInt,const Vec[],PetscScalar*);/* z[j] = x dot y[j] */ 1404bcd95a3SBarry Smith PetscErrorCode (*scale)(Vec,PetscScalar); /* x = alpha * x */ 1414bcd95a3SBarry Smith PetscErrorCode (*copy)(Vec,Vec); /* y = x */ 1424bcd95a3SBarry Smith PetscErrorCode (*set)(Vec,PetscScalar); /* y = alpha */ 1434bcd95a3SBarry Smith PetscErrorCode (*swap)(Vec,Vec); /* exchange x and y */ 1444bcd95a3SBarry Smith PetscErrorCode (*axpy)(Vec,PetscScalar,Vec); /* y = y + alpha * x */ 1454bcd95a3SBarry Smith PetscErrorCode (*axpby)(Vec,PetscScalar,PetscScalar,Vec); /* y = alpha * x + beta * y*/ 1464bcd95a3SBarry Smith PetscErrorCode (*maxpy)(Vec,PetscInt,const PetscScalar*,Vec*); /* y = y + alpha[j] x[j] */ 1474bcd95a3SBarry Smith ... (AND SO ON) ... 1484bcd95a3SBarry Smith}; 1494bcd95a3SBarry Smith``` 1504bcd95a3SBarry Smith 1514bcd95a3SBarry Smith``` 1524bcd95a3SBarry Smithstruct _p_Vec { 1534bcd95a3SBarry Smith PetscClassId classid; 1544bcd95a3SBarry Smith PetscOps *bops; 1554bcd95a3SBarry Smith VecOps *ops; 1564bcd95a3SBarry Smith MPI_Comm comm; 1574bcd95a3SBarry Smith PetscLogDouble flops,time,mem; 1584bcd95a3SBarry Smith int id; 1594bcd95a3SBarry Smith int refct; 1604bcd95a3SBarry Smith int tag; 1614bcd95a3SBarry Smith DLList qlist; 1624bcd95a3SBarry Smith OList olist; 1634bcd95a3SBarry Smith char *type_name; 1644bcd95a3SBarry Smith PetscObject parent; 1654bcd95a3SBarry Smith char *name; 1664bcd95a3SBarry Smith char *prefix; 1674bcd95a3SBarry Smith void **fortran_func_pointers; 1684bcd95a3SBarry Smith void *data; /* implementation-specific data */ 1694bcd95a3SBarry Smith PetscLayout map; 1704bcd95a3SBarry Smith ISLocalToGlobalMapping mapping; /* mapping used in VecSetValuesLocal() */ 1714bcd95a3SBarry Smith}; 1724bcd95a3SBarry Smith``` 1734bcd95a3SBarry Smith 1744bcd95a3SBarry SmithEach PETSc object begins with a `PetscClassId`, which is used for 1754bcd95a3SBarry Smitherror checking. Each different class of objects has its value for 1764bcd95a3SBarry Smith`classid`; these are used to distinguish between classes. When a new 1774bcd95a3SBarry Smithclass is created you need to call 1784bcd95a3SBarry Smith 1794bcd95a3SBarry Smith``` 1804bcd95a3SBarry SmithPetscClassIdRegister(const char *classname,PetscClassId *classid); 1814bcd95a3SBarry Smith``` 1824bcd95a3SBarry Smith 1834bcd95a3SBarry SmithFor example, 1844bcd95a3SBarry Smith 1854bcd95a3SBarry Smith``` 1864bcd95a3SBarry SmithPetscClassIdRegister("index set",&IS_CLASSID); 1874bcd95a3SBarry Smith``` 1884bcd95a3SBarry Smith 1894bcd95a3SBarry Smithyou can verify that an object is valid of a particular class with 1904bcd95a3SBarry Smith`PetscValidHeaderSpecific`, for example, 1914bcd95a3SBarry Smith 1924bcd95a3SBarry Smith``` 1934bcd95a3SBarry SmithPetscValidHeaderSpecific(x,VEC_CLASSID,1); 1944bcd95a3SBarry Smith``` 1954bcd95a3SBarry Smith 1964bcd95a3SBarry SmithThe third argument to this macro indicates the position in the calling 1974bcd95a3SBarry Smithsequence of the function the object was passed in. This is to generate 1984bcd95a3SBarry Smithmore complete error messages. 1994bcd95a3SBarry Smith 2004bcd95a3SBarry SmithTo check for an object of any type, use 2014bcd95a3SBarry Smith 2024bcd95a3SBarry Smith``` 2034bcd95a3SBarry SmithPetscValidHeader(x,1); 2044bcd95a3SBarry Smith``` 2054bcd95a3SBarry Smith 2064bcd95a3SBarry SmithThe `obj->ops` functions provide implementations of the standard methods of the object class. Each type 2074bcd95a3SBarry Smithof the class may have different function pointers in the array. Subtypes sometimes replace some of the 2084bcd95a3SBarry Smithfunction pointers of the parent, so they play the role of virtual methods in C++. 2094bcd95a3SBarry Smith 2104bcd95a3SBarry SmithPETSc code that calls these function pointers should be done via 2114bcd95a3SBarry Smith 2124bcd95a3SBarry Smith``` 2134bcd95a3SBarry SmithPetscUseTypeMethod(obj,method,other arguments); 2144bcd95a3SBarry SmithPetscTryTypeMethod(obj,method,other arguments); 2154bcd95a3SBarry Smith``` 2164bcd95a3SBarry Smith 2174bcd95a3SBarry SmithFor example, 2184bcd95a3SBarry Smith 2194bcd95a3SBarry Smith``` 2204bcd95a3SBarry SmithPetscErrorCode XXXOp(XXX x,YYY y) 2214bcd95a3SBarry Smith{ 2224bcd95a3SBarry Smith PetscFunctionBegin; 2234bcd95a3SBarry Smith PetscUseTypeMethod(x,op,y); 2244bcd95a3SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 2254bcd95a3SBarry Smith} 2264bcd95a3SBarry Smith``` 2274bcd95a3SBarry Smith 2284bcd95a3SBarry SmithThe `Try` variant skips the function call if the method has not been set while the `Use` version generates an error in that case. 2294bcd95a3SBarry Smith 2304bcd95a3SBarry SmithSee also, `PetscUseMethod()`, and `PetscTryMethod()`. 2314bcd95a3SBarry Smith 2324bcd95a3SBarry Smith## Common Object Functions 2334bcd95a3SBarry Smith 2344bcd95a3SBarry SmithSeveral routines are provided for manipulating data within the header. 2354bcd95a3SBarry SmithThese include the specific functions in the PETSc common function table. 2364bcd95a3SBarry SmithThe function pointers are not called directly; rather you should call 2374bcd95a3SBarry Smith`PetscObjectFunctionName()`, where `FunctionName` is one of the 2384bcd95a3SBarry Smithfunctions listed below with the first letter of each word capitalized. 2394bcd95a3SBarry Smith 240*7f296bb3SBarry Smith`PetscObjectGetComm()` calls the `getcomm(PetscObject,MPI_Comm*)` function point which obtains the MPI communicator 2414bcd95a3SBarry Smithassociated with this object. 2424bcd95a3SBarry Smith 243*7f296bb3SBarry Smith`PetscObjectView()` calls the `view(PetscObject,PetscViewer)` function point which allows you to store or visualize the 244*7f296bb3SBarry Smithdata inside an object. If the `PetscViewer` is `NULL`, then it should cause the 245*7f296bb3SBarry Smithobject to print information on the object to `stdout`. 2464bcd95a3SBarry Smith 247*7f296bb3SBarry Smith`PetscObjectDestroy()` calls the `destroy(PetscObject)` function pointer which causes the reference count of the object to be 2484bcd95a3SBarry Smithdecreased by one or the object to be destroyed and all memory used by 2494bcd95a3SBarry Smiththe object to be freed when the reference count drops to zero. If the 250*7f296bb3SBarry Smithobject has any other objects composed with it, the `PetscObjectDestroy()` function is called on them. 2514bcd95a3SBarry Smith 252*7f296bb3SBarry Smith`PetscObjectCompose()` calls the `compose(PetscObject,const char *name,PetscObject)` function pointer which associates the 2534bcd95a3SBarry Smithsecond object with the first object and increases the reference count of 2544bcd95a3SBarry Smiththe second object. If an object with the same name was previously 2554bcd95a3SBarry Smithcomposed, that object is dereferenced and replaced with the new object. 256*7f296bb3SBarry SmithIf the second object is `NULL` and an object with the same name has 257*7f296bb3SBarry Smithalready been composed, that object is dereferenced (the `PetscObjectDestroy()` 2584bcd95a3SBarry Smithfunction is called on it, and that object is removed from the first 2594bcd95a3SBarry Smithobject). This is a way to remove, by name, an object that was previously 2604bcd95a3SBarry Smithcomposed. 2614bcd95a3SBarry Smith 262*7f296bb3SBarry Smith`PetscObjectQuery()` calls the `query(PetscObject,const char *name,PetscObject*)` function pointer which retrieves an object 2634bcd95a3SBarry Smiththat was previously composed with the first object via 264*7f296bb3SBarry Smith`PetscObjectCompose()`. It retrieves a `NULL` if no object with that 2654bcd95a3SBarry Smithname was previously composed. 2664bcd95a3SBarry Smith 267*7f296bb3SBarry Smith`PetscObjectComposeFunction()` calls the `composefunction(PetscObject,const char *name,void *func)` function pointer which associates 2684bcd95a3SBarry Smitha function pointer with an object. If the object already had a composed 2694bcd95a3SBarry Smithfunction with the same name, the old one is replaced. If `func` is 2704bcd95a3SBarry Smith`NULL`, the existing function is removed from the object. The string 2714bcd95a3SBarry Smith`name` is the character string name of the function. 2724bcd95a3SBarry Smith 2734bcd95a3SBarry SmithFor example, `fname` may be `PCCreate_LU`. 2744bcd95a3SBarry Smith 275*7f296bb3SBarry Smith`PetscObjectQueryFunction()` calls the `queryfunction(PetscObject,const char *name,void **func)` function pointer which retrieves a 2764bcd95a3SBarry Smithfunction pointer that was associated with the object via 2774bcd95a3SBarry Smith`PetscObjectComposeFunction()`. If dynamic libraries are used, the 2784bcd95a3SBarry Smithfunction is loaded into memory at this time (if it has not been 279*7f296bb3SBarry Smithpreviously loaded), not when the `PetscObjectComposeFunction()` routine was 2804bcd95a3SBarry Smithcalled. 2814bcd95a3SBarry Smith 2824bcd95a3SBarry SmithSince the object composition allows one to compose PETSc objects 2834bcd95a3SBarry Smithwith PETSc objects, PETSc provides the 2844bcd95a3SBarry Smithconvenience object `PetscContainer`, created with the routine 2854bcd95a3SBarry Smith`PetscContainerCreate(MPI_Comm,PetscContainer*)`, to allow wrapping any 2864bcd95a3SBarry Smithkind of data into a PETSc object that can then be composed with a PETSc 287*7f296bb3SBarry Smithobject. One can also use `PetscObjectContainerCompose()` and `PetscObjectContainerQuery()` to compose 2884bcd95a3SBarry Smitharbitrary pointers with a PETSc object. 2894bcd95a3SBarry Smith 2904bcd95a3SBarry Smith## Object Function Implementation 2914bcd95a3SBarry Smith 2924bcd95a3SBarry SmithThis section discusses how PETSc implements the `compose()`, 2934bcd95a3SBarry Smith`query()`, `composefunction()`, and `queryfunction()` functions 2944bcd95a3SBarry Smithfor its object implementations. Other PETSc-compatible class 2954bcd95a3SBarry Smithimplementations are free to manage these functions in any manner; but 2964bcd95a3SBarry Smithunless there is a specific reason, they should use the PETSc defaults so 2974bcd95a3SBarry Smiththat the library writer does not have to “reinvent the wheel.” 2984bcd95a3SBarry Smith 2994bcd95a3SBarry Smith### Compose and Query Objects 3004bcd95a3SBarry Smith 3014bcd95a3SBarry SmithIn 3024bcd95a3SBarry Smith<a href="PETSC_DOC_OUT_ROOT_PLACEHOLDER/src/sys/objects/olist.c.html">src/sys/objects/olist.c</a> 3034bcd95a3SBarry SmithPETSc defines a C `struct` 3044bcd95a3SBarry Smith 3054bcd95a3SBarry Smith``` 3064bcd95a3SBarry Smithtypedef struct _PetscObjectList* PetscObjectList; 3074bcd95a3SBarry Smithstruct _PetscObjectList { 3084bcd95a3SBarry Smith char name[128]; 3094bcd95a3SBarry Smith PetscObject obj; 3104bcd95a3SBarry Smith PetscObjectList next; 3114bcd95a3SBarry Smith}; 3124bcd95a3SBarry Smith``` 3134bcd95a3SBarry Smith 3144bcd95a3SBarry Smithfrom which linked lists of composed objects may be constructed. The 3154bcd95a3SBarry Smithroutines to manipulate these elementary objects are 3164bcd95a3SBarry Smith 3174bcd95a3SBarry Smith``` 3184bcd95a3SBarry Smithint PetscObjectListAdd(PetscObjectList *fl,const char *name,PetscObject obj); 3194bcd95a3SBarry Smithint PetscObjectListDestroy(PetscObjectList *fl); 3204bcd95a3SBarry Smithint PetscObjectListFind(PetscObjectList fl,const char *name,PetscObject *obj) 3214bcd95a3SBarry Smithint PetscObjectListDuplicate(PetscObjectList fl,PetscObjectList *nl); 3224bcd95a3SBarry Smith``` 3234bcd95a3SBarry Smith 3244bcd95a3SBarry SmithThe function `PetscObjectListAdd()` will create the initial 3254bcd95a3SBarry SmithPetscObjectList if the argument `fl` points to a NULL. 3264bcd95a3SBarry Smith 3274bcd95a3SBarry SmithThe PETSc object `compose()` and `query()` functions are as follows 3284bcd95a3SBarry Smith(defined in 3294bcd95a3SBarry Smith<a href="PETSC_DOC_OUT_ROOT_PLACEHOLDER/src/sys/objects/inherit.c.html">src/sys/objects/inherit.c</a> 3304bcd95a3SBarry Smith 3314bcd95a3SBarry Smith``` 3324bcd95a3SBarry SmithPetscErrorCode PetscObjectCompose_Petsc(PetscObject obj,const char *name,PetscObject ptr) 3334bcd95a3SBarry Smith{ 3344bcd95a3SBarry Smith PetscFunctionBegin; 3354bcd95a3SBarry Smith PetscCall(PetscObjectListAdd(&obj->olist,name,ptr)); 3364bcd95a3SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 3374bcd95a3SBarry Smith} 3384bcd95a3SBarry Smith 3394bcd95a3SBarry SmithPetscErrorCode PetscObjectQuery_Petsc(PetscObject obj,const char *name,PetscObject *ptr) 3404bcd95a3SBarry Smith{ 3414bcd95a3SBarry Smith PetscFunctionBegin; 3424bcd95a3SBarry Smith PetscCall(PetscObjectListFind(obj->olist,name,ptr)); 3434bcd95a3SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 3444bcd95a3SBarry Smith} 3454bcd95a3SBarry Smith``` 3464bcd95a3SBarry Smith 3474bcd95a3SBarry Smith### Compose and Query Functions 3484bcd95a3SBarry Smith 3494bcd95a3SBarry SmithPETSc allows you to compose functions by specifying a name and function 3504bcd95a3SBarry Smithpointer. In 3514bcd95a3SBarry Smith<a href="PETSC_DOC_OUT_ROOT_PLACEHOLDER/src/sys/dll/reg.c.html">src/sys/dll/reg.c</a> 3524bcd95a3SBarry SmithPETSc defines the following linked list structure. 3534bcd95a3SBarry Smith 3544bcd95a3SBarry Smith``` 3554bcd95a3SBarry Smithstruct _n_PetscFunctionList { 3564bcd95a3SBarry Smith void (*routine)(void); /* the routine */ 3574bcd95a3SBarry Smith char *name; /* string to identify routine */ 3584bcd95a3SBarry Smith PetscFunctionList next; /* next pointer */ 3594bcd95a3SBarry Smith PetscFunctionList next_list; /* used to maintain list of all lists for freeing */ 3604bcd95a3SBarry Smith}; 3614bcd95a3SBarry Smith``` 3624bcd95a3SBarry Smith 3634bcd95a3SBarry SmithEach PETSc object contains a `PetscFunctionList` object. The 3644bcd95a3SBarry Smith`composefunction()` and `queryfunction()` are given by the 3654bcd95a3SBarry Smithfollowing. 3664bcd95a3SBarry Smith 3674bcd95a3SBarry Smith``` 3684bcd95a3SBarry SmithPetscErrorCode PetscObjectComposeFunction_Petsc(PetscObject obj,const char *name,void *ptr) 3694bcd95a3SBarry Smith{ 3704bcd95a3SBarry Smith PetscFunctionBegin; 3714bcd95a3SBarry Smith PetscCall(PetscFunctionListAdd(&obj->qlist,name,fname,ptr)); 3724bcd95a3SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 3734bcd95a3SBarry Smith} 3744bcd95a3SBarry Smith 3754bcd95a3SBarry SmithPetscErrorCode PetscObjectQueryFunction_Petsc(PetscObject obj,const char *name,void (**ptr)(void)) 3764bcd95a3SBarry Smith{ 3774bcd95a3SBarry Smith PetscFunctionBegin; 3784bcd95a3SBarry Smith PetscCall(PetscFunctionListFind(obj->qlist,name,ptr)); 3794bcd95a3SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 3804bcd95a3SBarry Smith} 3814bcd95a3SBarry Smith``` 3824bcd95a3SBarry Smith 3834bcd95a3SBarry SmithIn addition to using the `PetscFunctionList` mechanism to compose 3844bcd95a3SBarry Smithfunctions into PETSc objects, it is also used to allow registration of 3854bcd95a3SBarry Smithnew class implementations; for example, new preconditioners. 3864bcd95a3SBarry Smith 3874bcd95a3SBarry SmithPETSc code that calls composed functions should be done via 3884bcd95a3SBarry Smith 3894bcd95a3SBarry Smith``` 3904bcd95a3SBarry SmithPetscUseMethod(obj,"method",(Argument types),(argument variables)); 3914bcd95a3SBarry SmithPetscTryMethod(obj,"method",(Argument types),(argument variables)); 3924bcd95a3SBarry Smith``` 3934bcd95a3SBarry Smith 3944bcd95a3SBarry SmithFor example, 3954bcd95a3SBarry Smith 3964bcd95a3SBarry Smith``` 3974bcd95a3SBarry SmithPetscErrorCode KSPGMRESSetRestart(KSP ksp, PetscInt restart) 3984bcd95a3SBarry Smith{ 3994bcd95a3SBarry Smith PetscFunctionBegin; 4004bcd95a3SBarry Smith PetscValidLogicalCollectiveInt(ksp,restart,2); 4014bcd95a3SBarry Smith 4024bcd95a3SBarry Smith PetscTryMethod(ksp,"KSPGMRESSetRestart_C",(KSP,PetscInt),(ksp,restart)); 4034bcd95a3SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 4044bcd95a3SBarry Smith} 4054bcd95a3SBarry Smith``` 4064bcd95a3SBarry Smith 4074bcd95a3SBarry SmithThe `Try` variant skips the function call if the method has not been composed with 4084bcd95a3SBarry Smiththe object while the `Use` version generates an error in that case. 4094bcd95a3SBarry SmithSee also, `PetscUseTypeMethod()`, and `PetscTryTypeMethod()`. 4104bcd95a3SBarry Smith 4114bcd95a3SBarry Smith### Simple PETSc Objects 4124bcd95a3SBarry Smith 4134bcd95a3SBarry SmithSome simple PETSc objects do not need `PETSCHEADER` and the associated 4144bcd95a3SBarry Smithfunctionality. These objects are internally named as `_n_<class>` as 4154bcd95a3SBarry Smithopposed to `_p_<class>`, for example, `_n_PetscFunctionList` vs `_p_Vec`. 4164bcd95a3SBarry Smith 4174bcd95a3SBarry Smith## PETSc Packages 4184bcd95a3SBarry Smith 4194bcd95a3SBarry SmithThe PETSc source code is divided into the following library-level 4204bcd95a3SBarry Smithpackages: `Sys`, `Vec`, `Mat`, `DM`, `KSP`, `SNES`, `TS`, 4214bcd95a3SBarry Smith`Tao`. Each of these has a directory under the `src` directory in 4224bcd95a3SBarry Smiththe PETSc tree and, optionally, can be compiled into separate libraries. 4234bcd95a3SBarry SmithEach package defines one or more classes; for example, the `KSP` 4244bcd95a3SBarry Smithpackage defines the `KSP` and `PC` classes, as well as several 4254bcd95a3SBarry Smithutility classes. In addition, each library-level package may contain 4264bcd95a3SBarry Smithseveral class-level packages associated with individual classes in the 4274bcd95a3SBarry Smithlibrary-level package. In general, most “important” classes in PETSc 4284bcd95a3SBarry Smithhave their own class level package. Each package provides a registration 4294bcd95a3SBarry Smithfunction `XXXInitializePackage()`, for example 4304bcd95a3SBarry Smith`KSPInitializePackage()`, which registers all the classes and events 4314bcd95a3SBarry Smithfor that package. Each package also registers a finalization routine, 4324bcd95a3SBarry Smith`XXXFinalizePackage()`, that releases all the resources used in 4334bcd95a3SBarry Smithregistering the package, using `PetscRegisterFinalize()`. The 4344bcd95a3SBarry Smithregistration for each package is performed “on demand” the first time a 4354bcd95a3SBarry Smithclass in the package is utilized. This is handled, for example, with 4364bcd95a3SBarry Smithcode such as 4374bcd95a3SBarry Smith 4384bcd95a3SBarry Smith``` 4394bcd95a3SBarry SmithPetscErrorCode VecCreate(MPI_Comm comm, Vec *vec) 4404bcd95a3SBarry Smith{ 4414bcd95a3SBarry Smith Vec v; 4424bcd95a3SBarry Smith 4434bcd95a3SBarry Smith PetscFunctionBegin; 4444bcd95a3SBarry Smith PetscAssertPointer(vec,2); 4454bcd95a3SBarry Smith *vec = NULL; 4464bcd95a3SBarry Smith VecInitializePackage(); 4474bcd95a3SBarry Smith ... 4484bcd95a3SBarry Smith``` 449