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 847f296bb3SBarry 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 (*view)(PetscObject, Viewer); 914bcd95a3SBarry Smith PetscErrorCode (*destroy)(PetscObject); 924bcd95a3SBarry Smith} PetscOps; 934bcd95a3SBarry Smith``` 944bcd95a3SBarry Smith 954bcd95a3SBarry Smith``` 964bcd95a3SBarry Smithstruct _p_<class> { 974bcd95a3SBarry Smith PetscClassId classid; 984bcd95a3SBarry Smith PetscOps *bops; 994bcd95a3SBarry Smith <class>Ops *ops; 1004bcd95a3SBarry Smith MPI_Comm comm; 1014bcd95a3SBarry Smith PetscLogDouble flops,time,mem; 1024bcd95a3SBarry Smith int id; 1034bcd95a3SBarry Smith int refct; 1044bcd95a3SBarry Smith int tag; 1054bcd95a3SBarry Smith DLList qlist; 1064bcd95a3SBarry Smith OList olist; 1074bcd95a3SBarry Smith char *type_name; 1084bcd95a3SBarry Smith PetscObject parent; 1094bcd95a3SBarry Smith char *name; 1104bcd95a3SBarry Smith char *prefix; 1114bcd95a3SBarry Smith void *cpp; 1124bcd95a3SBarry Smith void **fortran_func_pointers; 1134bcd95a3SBarry Smith .......... 1144bcd95a3SBarry Smith CLASS-SPECIFIC DATASTRUCTURES 1154bcd95a3SBarry Smith}; 1164bcd95a3SBarry Smith``` 1174bcd95a3SBarry Smith 1184bcd95a3SBarry SmithHere `<class>ops` is a function table (like the `PetscOps` above) 1194bcd95a3SBarry Smiththat contains the function pointers for the operations specific to that 1204bcd95a3SBarry Smithclass. For example, the PETSc vector class object operations in 1214bcd95a3SBarry Smith<a href="PETSC_DOC_OUT_ROOT_PLACEHOLDER/include/petsc/private/vecimpl.h.html">include/petsc/private/vecimpl.h</a> 1224bcd95a3SBarry Smithinclude the following. 1234bcd95a3SBarry Smith 1244bcd95a3SBarry Smith``` 1254bcd95a3SBarry Smithtypedef struct _VecOps* VecOps; 1264bcd95a3SBarry Smithstruct _VecOps { 1274bcd95a3SBarry Smith PetscErrorCode (*duplicate)(Vec,Vec*); /* get single vector */ 1284bcd95a3SBarry Smith PetscErrorCode (*duplicatevecs)(Vec,PetscInt,Vec**); /* get array of vectors */ 1294bcd95a3SBarry Smith PetscErrorCode (*destroyvecs)(PetscInt,Vec[]); /* free array of vectors */ 1304bcd95a3SBarry Smith PetscErrorCode (*dot)(Vec,Vec,PetscScalar*); /* z = x^H * y */ 1314bcd95a3SBarry Smith PetscErrorCode (*mdot)(Vec,PetscInt,const Vec[],PetscScalar*); /* z[j] = x dot y[j] */ 1324bcd95a3SBarry Smith PetscErrorCode (*norm)(Vec,NormType,PetscReal*); /* z = sqrt(x^H * x) */ 1334bcd95a3SBarry Smith PetscErrorCode (*tdot)(Vec,Vec,PetscScalar*); /* x'*y */ 1344bcd95a3SBarry Smith PetscErrorCode (*mtdot)(Vec,PetscInt,const Vec[],PetscScalar*);/* z[j] = x dot y[j] */ 1354bcd95a3SBarry Smith PetscErrorCode (*scale)(Vec,PetscScalar); /* x = alpha * x */ 1364bcd95a3SBarry Smith PetscErrorCode (*copy)(Vec,Vec); /* y = x */ 1374bcd95a3SBarry Smith PetscErrorCode (*set)(Vec,PetscScalar); /* y = alpha */ 1384bcd95a3SBarry Smith PetscErrorCode (*swap)(Vec,Vec); /* exchange x and y */ 1394bcd95a3SBarry Smith PetscErrorCode (*axpy)(Vec,PetscScalar,Vec); /* y = y + alpha * x */ 1404bcd95a3SBarry Smith PetscErrorCode (*axpby)(Vec,PetscScalar,PetscScalar,Vec); /* y = alpha * x + beta * y*/ 1414bcd95a3SBarry Smith PetscErrorCode (*maxpy)(Vec,PetscInt,const PetscScalar*,Vec*); /* y = y + alpha[j] x[j] */ 1424bcd95a3SBarry Smith ... (AND SO ON) ... 1434bcd95a3SBarry Smith}; 1444bcd95a3SBarry Smith``` 1454bcd95a3SBarry Smith 1464bcd95a3SBarry Smith``` 1474bcd95a3SBarry Smithstruct _p_Vec { 1484bcd95a3SBarry Smith PetscClassId classid; 1494bcd95a3SBarry Smith PetscOps *bops; 1504bcd95a3SBarry Smith VecOps *ops; 1514bcd95a3SBarry Smith MPI_Comm comm; 1524bcd95a3SBarry Smith PetscLogDouble flops,time,mem; 1534bcd95a3SBarry Smith int id; 1544bcd95a3SBarry Smith int refct; 1554bcd95a3SBarry Smith int tag; 1564bcd95a3SBarry Smith DLList qlist; 1574bcd95a3SBarry Smith OList olist; 1584bcd95a3SBarry Smith char *type_name; 1594bcd95a3SBarry Smith PetscObject parent; 1604bcd95a3SBarry Smith char *name; 1614bcd95a3SBarry Smith char *prefix; 1624bcd95a3SBarry Smith void **fortran_func_pointers; 1634bcd95a3SBarry Smith void *data; /* implementation-specific data */ 1644bcd95a3SBarry Smith PetscLayout map; 1654bcd95a3SBarry Smith ISLocalToGlobalMapping mapping; /* mapping used in VecSetValuesLocal() */ 1664bcd95a3SBarry Smith}; 1674bcd95a3SBarry Smith``` 1684bcd95a3SBarry Smith 1694bcd95a3SBarry SmithEach PETSc object begins with a `PetscClassId`, which is used for 1704bcd95a3SBarry Smitherror checking. Each different class of objects has its value for 1714bcd95a3SBarry Smith`classid`; these are used to distinguish between classes. When a new 1724bcd95a3SBarry Smithclass is created you need to call 1734bcd95a3SBarry Smith 1744bcd95a3SBarry Smith``` 1754bcd95a3SBarry SmithPetscClassIdRegister(const char *classname,PetscClassId *classid); 1764bcd95a3SBarry Smith``` 1774bcd95a3SBarry Smith 1784bcd95a3SBarry SmithFor example, 1794bcd95a3SBarry Smith 1804bcd95a3SBarry Smith``` 1814bcd95a3SBarry SmithPetscClassIdRegister("index set",&IS_CLASSID); 1824bcd95a3SBarry Smith``` 1834bcd95a3SBarry Smith 1844bcd95a3SBarry Smithyou can verify that an object is valid of a particular class with 1854bcd95a3SBarry Smith`PetscValidHeaderSpecific`, for example, 1864bcd95a3SBarry Smith 1874bcd95a3SBarry Smith``` 1884bcd95a3SBarry SmithPetscValidHeaderSpecific(x,VEC_CLASSID,1); 1894bcd95a3SBarry Smith``` 1904bcd95a3SBarry Smith 1914bcd95a3SBarry SmithThe third argument to this macro indicates the position in the calling 1924bcd95a3SBarry Smithsequence of the function the object was passed in. This is to generate 1934bcd95a3SBarry Smithmore complete error messages. 1944bcd95a3SBarry Smith 1954bcd95a3SBarry SmithTo check for an object of any type, use 1964bcd95a3SBarry Smith 1974bcd95a3SBarry Smith``` 1984bcd95a3SBarry SmithPetscValidHeader(x,1); 1994bcd95a3SBarry Smith``` 2004bcd95a3SBarry Smith 2014bcd95a3SBarry SmithThe `obj->ops` functions provide implementations of the standard methods of the object class. Each type 2024bcd95a3SBarry Smithof the class may have different function pointers in the array. Subtypes sometimes replace some of the 2034bcd95a3SBarry Smithfunction pointers of the parent, so they play the role of virtual methods in C++. 2044bcd95a3SBarry Smith 2054bcd95a3SBarry SmithPETSc code that calls these function pointers should be done via 2064bcd95a3SBarry Smith 2074bcd95a3SBarry Smith``` 2084bcd95a3SBarry SmithPetscUseTypeMethod(obj,method,other arguments); 2094bcd95a3SBarry SmithPetscTryTypeMethod(obj,method,other arguments); 2104bcd95a3SBarry Smith``` 2114bcd95a3SBarry Smith 2124bcd95a3SBarry SmithFor example, 2134bcd95a3SBarry Smith 2144bcd95a3SBarry Smith``` 2154bcd95a3SBarry SmithPetscErrorCode XXXOp(XXX x,YYY y) 2164bcd95a3SBarry Smith{ 2174bcd95a3SBarry Smith PetscFunctionBegin; 2184bcd95a3SBarry Smith PetscUseTypeMethod(x,op,y); 2194bcd95a3SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 2204bcd95a3SBarry Smith} 2214bcd95a3SBarry Smith``` 2224bcd95a3SBarry Smith 2234bcd95a3SBarry SmithThe `Try` variant skips the function call if the method has not been set while the `Use` version generates an error in that case. 2244bcd95a3SBarry Smith 2254bcd95a3SBarry SmithSee also, `PetscUseMethod()`, and `PetscTryMethod()`. 2264bcd95a3SBarry Smith 2274bcd95a3SBarry Smith## Common Object Functions 2284bcd95a3SBarry Smith 2294bcd95a3SBarry SmithSeveral routines are provided for manipulating data within the header. 2304bcd95a3SBarry SmithThese include the specific functions in the PETSc common function table. 2314bcd95a3SBarry SmithThe function pointers are not called directly; rather you should call 2324bcd95a3SBarry Smith`PetscObjectFunctionName()`, where `FunctionName` is one of the 2334bcd95a3SBarry Smithfunctions listed below with the first letter of each word capitalized. 2344bcd95a3SBarry Smith 2357f296bb3SBarry Smith`PetscObjectGetComm()` calls the `getcomm(PetscObject,MPI_Comm*)` function point which obtains the MPI communicator 2364bcd95a3SBarry Smithassociated with this object. 2374bcd95a3SBarry Smith 2387f296bb3SBarry Smith`PetscObjectView()` calls the `view(PetscObject,PetscViewer)` function point which allows you to store or visualize the 2397f296bb3SBarry Smithdata inside an object. If the `PetscViewer` is `NULL`, then it should cause the 2407f296bb3SBarry Smithobject to print information on the object to `stdout`. 2414bcd95a3SBarry Smith 2427f296bb3SBarry Smith`PetscObjectDestroy()` calls the `destroy(PetscObject)` function pointer which causes the reference count of the object to be 2434bcd95a3SBarry Smithdecreased by one or the object to be destroyed and all memory used by 2444bcd95a3SBarry Smiththe object to be freed when the reference count drops to zero. If the 2457f296bb3SBarry Smithobject has any other objects composed with it, the `PetscObjectDestroy()` function is called on them. 2464bcd95a3SBarry Smith 2477f296bb3SBarry Smith`PetscObjectCompose()` calls the `compose(PetscObject,const char *name,PetscObject)` function pointer which associates the 2484bcd95a3SBarry Smithsecond object with the first object and increases the reference count of 2494bcd95a3SBarry Smiththe second object. If an object with the same name was previously 2504bcd95a3SBarry Smithcomposed, that object is dereferenced and replaced with the new object. 2517f296bb3SBarry SmithIf the second object is `NULL` and an object with the same name has 2527f296bb3SBarry Smithalready been composed, that object is dereferenced (the `PetscObjectDestroy()` 2534bcd95a3SBarry Smithfunction is called on it, and that object is removed from the first 2544bcd95a3SBarry Smithobject). This is a way to remove, by name, an object that was previously 2554bcd95a3SBarry Smithcomposed. 2564bcd95a3SBarry Smith 2577f296bb3SBarry Smith`PetscObjectQuery()` calls the `query(PetscObject,const char *name,PetscObject*)` function pointer which retrieves an object 2584bcd95a3SBarry Smiththat was previously composed with the first object via 2597f296bb3SBarry Smith`PetscObjectCompose()`. It retrieves a `NULL` if no object with that 2604bcd95a3SBarry Smithname was previously composed. 2614bcd95a3SBarry Smith 2627f296bb3SBarry Smith`PetscObjectComposeFunction()` calls the `composefunction(PetscObject,const char *name,void *func)` function pointer which associates 2634bcd95a3SBarry Smitha function pointer with an object. If the object already had a composed 2644bcd95a3SBarry Smithfunction with the same name, the old one is replaced. If `func` is 2654bcd95a3SBarry Smith`NULL`, the existing function is removed from the object. The string 2664bcd95a3SBarry Smith`name` is the character string name of the function. 2674bcd95a3SBarry Smith 2684bcd95a3SBarry SmithFor example, `fname` may be `PCCreate_LU`. 2694bcd95a3SBarry Smith 2707f296bb3SBarry Smith`PetscObjectQueryFunction()` calls the `queryfunction(PetscObject,const char *name,void **func)` function pointer which retrieves a 2714bcd95a3SBarry Smithfunction pointer that was associated with the object via 2724bcd95a3SBarry Smith`PetscObjectComposeFunction()`. If dynamic libraries are used, the 2734bcd95a3SBarry Smithfunction is loaded into memory at this time (if it has not been 2747f296bb3SBarry Smithpreviously loaded), not when the `PetscObjectComposeFunction()` routine was 2754bcd95a3SBarry Smithcalled. 2764bcd95a3SBarry Smith 2774bcd95a3SBarry SmithSince the object composition allows one to compose PETSc objects 2784bcd95a3SBarry Smithwith PETSc objects, PETSc provides the 2794bcd95a3SBarry Smithconvenience object `PetscContainer`, created with the routine 2804bcd95a3SBarry Smith`PetscContainerCreate(MPI_Comm,PetscContainer*)`, to allow wrapping any 2814bcd95a3SBarry Smithkind of data into a PETSc object that can then be composed with a PETSc 2827f296bb3SBarry Smithobject. One can also use `PetscObjectContainerCompose()` and `PetscObjectContainerQuery()` to compose 2834bcd95a3SBarry Smitharbitrary pointers with a PETSc object. 2844bcd95a3SBarry Smith 2854bcd95a3SBarry Smith## Object Function Implementation 2864bcd95a3SBarry Smith 2874bcd95a3SBarry SmithThis section discusses how PETSc implements the `compose()`, 2884bcd95a3SBarry Smith`query()`, `composefunction()`, and `queryfunction()` functions 2894bcd95a3SBarry Smithfor its object implementations. Other PETSc-compatible class 2904bcd95a3SBarry Smithimplementations are free to manage these functions in any manner; but 2914bcd95a3SBarry Smithunless there is a specific reason, they should use the PETSc defaults so 2924bcd95a3SBarry Smiththat the library writer does not have to “reinvent the wheel.” 2934bcd95a3SBarry Smith 2944bcd95a3SBarry Smith### Compose and Query Objects 2954bcd95a3SBarry Smith 2964bcd95a3SBarry SmithIn 2974bcd95a3SBarry Smith<a href="PETSC_DOC_OUT_ROOT_PLACEHOLDER/src/sys/objects/olist.c.html">src/sys/objects/olist.c</a> 2984bcd95a3SBarry SmithPETSc defines a C `struct` 2994bcd95a3SBarry Smith 3004bcd95a3SBarry Smith``` 3014bcd95a3SBarry Smithtypedef struct _PetscObjectList* PetscObjectList; 3024bcd95a3SBarry Smithstruct _PetscObjectList { 3034bcd95a3SBarry Smith char name[128]; 3044bcd95a3SBarry Smith PetscObject obj; 3054bcd95a3SBarry Smith PetscObjectList next; 3064bcd95a3SBarry Smith}; 3074bcd95a3SBarry Smith``` 3084bcd95a3SBarry Smith 3094bcd95a3SBarry Smithfrom which linked lists of composed objects may be constructed. The 3104bcd95a3SBarry Smithroutines to manipulate these elementary objects are 3114bcd95a3SBarry Smith 3124bcd95a3SBarry Smith``` 3134bcd95a3SBarry Smithint PetscObjectListAdd(PetscObjectList *fl,const char *name,PetscObject obj); 3144bcd95a3SBarry Smithint PetscObjectListDestroy(PetscObjectList *fl); 3154bcd95a3SBarry Smithint PetscObjectListFind(PetscObjectList fl,const char *name,PetscObject *obj) 3164bcd95a3SBarry Smithint PetscObjectListDuplicate(PetscObjectList fl,PetscObjectList *nl); 3174bcd95a3SBarry Smith``` 3184bcd95a3SBarry Smith 3194bcd95a3SBarry SmithThe function `PetscObjectListAdd()` will create the initial 3204bcd95a3SBarry SmithPetscObjectList if the argument `fl` points to a NULL. 3214bcd95a3SBarry Smith 3224bcd95a3SBarry SmithThe PETSc object `compose()` and `query()` functions are as follows 3234bcd95a3SBarry Smith(defined in 3244bcd95a3SBarry Smith<a href="PETSC_DOC_OUT_ROOT_PLACEHOLDER/src/sys/objects/inherit.c.html">src/sys/objects/inherit.c</a> 3254bcd95a3SBarry Smith 3264bcd95a3SBarry Smith``` 3274bcd95a3SBarry SmithPetscErrorCode PetscObjectCompose_Petsc(PetscObject obj,const char *name,PetscObject ptr) 3284bcd95a3SBarry Smith{ 3294bcd95a3SBarry Smith PetscFunctionBegin; 3304bcd95a3SBarry Smith PetscCall(PetscObjectListAdd(&obj->olist,name,ptr)); 3314bcd95a3SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 3324bcd95a3SBarry Smith} 3334bcd95a3SBarry Smith 3344bcd95a3SBarry SmithPetscErrorCode PetscObjectQuery_Petsc(PetscObject obj,const char *name,PetscObject *ptr) 3354bcd95a3SBarry Smith{ 3364bcd95a3SBarry Smith PetscFunctionBegin; 3374bcd95a3SBarry Smith PetscCall(PetscObjectListFind(obj->olist,name,ptr)); 3384bcd95a3SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 3394bcd95a3SBarry Smith} 3404bcd95a3SBarry Smith``` 3414bcd95a3SBarry Smith 3424bcd95a3SBarry Smith### Compose and Query Functions 3434bcd95a3SBarry Smith 3444bcd95a3SBarry SmithPETSc allows you to compose functions by specifying a name and function 3454bcd95a3SBarry Smithpointer. In 3464bcd95a3SBarry Smith<a href="PETSC_DOC_OUT_ROOT_PLACEHOLDER/src/sys/dll/reg.c.html">src/sys/dll/reg.c</a> 3474bcd95a3SBarry SmithPETSc defines the following linked list structure. 3484bcd95a3SBarry Smith 3494bcd95a3SBarry Smith``` 3504bcd95a3SBarry Smithstruct _n_PetscFunctionList { 3514bcd95a3SBarry Smith void (*routine)(void); /* the routine */ 3524bcd95a3SBarry Smith char *name; /* string to identify routine */ 3534bcd95a3SBarry Smith PetscFunctionList next; /* next pointer */ 3544bcd95a3SBarry Smith PetscFunctionList next_list; /* used to maintain list of all lists for freeing */ 3554bcd95a3SBarry Smith}; 3564bcd95a3SBarry Smith``` 3574bcd95a3SBarry Smith 3584bcd95a3SBarry SmithEach PETSc object contains a `PetscFunctionList` object. The 3594bcd95a3SBarry Smith`composefunction()` and `queryfunction()` are given by the 3604bcd95a3SBarry Smithfollowing. 3614bcd95a3SBarry Smith 3624bcd95a3SBarry Smith``` 363*57d50842SBarry SmithPetscErrorCode PetscObjectComposeFunction_Petsc(PetscObject obj, const char *name, PetscErrorCodeFn *ptr) 3644bcd95a3SBarry Smith{ 3654bcd95a3SBarry Smith PetscFunctionBegin; 3664bcd95a3SBarry Smith PetscCall(PetscFunctionListAdd(&obj->qlist,name,fname,ptr)); 3674bcd95a3SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 3684bcd95a3SBarry Smith} 3694bcd95a3SBarry Smith 370*57d50842SBarry SmithPetscErrorCode PetscObjectQueryFunction_Petsc(PetscObject obj, const char *name, PetscErrorCodeFn **ptr) 3714bcd95a3SBarry Smith{ 3724bcd95a3SBarry Smith PetscFunctionBegin; 3734bcd95a3SBarry Smith PetscCall(PetscFunctionListFind(obj->qlist,name,ptr)); 3744bcd95a3SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 3754bcd95a3SBarry Smith} 3764bcd95a3SBarry Smith``` 3774bcd95a3SBarry Smith 3784bcd95a3SBarry SmithIn addition to using the `PetscFunctionList` mechanism to compose 3794bcd95a3SBarry Smithfunctions into PETSc objects, it is also used to allow registration of 3804bcd95a3SBarry Smithnew class implementations; for example, new preconditioners. 3814bcd95a3SBarry Smith 3824bcd95a3SBarry SmithPETSc code that calls composed functions should be done via 3834bcd95a3SBarry Smith 3844bcd95a3SBarry Smith``` 3854bcd95a3SBarry SmithPetscUseMethod(obj,"method",(Argument types),(argument variables)); 3864bcd95a3SBarry SmithPetscTryMethod(obj,"method",(Argument types),(argument variables)); 3874bcd95a3SBarry Smith``` 3884bcd95a3SBarry Smith 3894bcd95a3SBarry SmithFor example, 3904bcd95a3SBarry Smith 3914bcd95a3SBarry Smith``` 3924bcd95a3SBarry SmithPetscErrorCode KSPGMRESSetRestart(KSP ksp, PetscInt restart) 3934bcd95a3SBarry Smith{ 3944bcd95a3SBarry Smith PetscFunctionBegin; 3954bcd95a3SBarry Smith PetscValidLogicalCollectiveInt(ksp,restart,2); 3964bcd95a3SBarry Smith 3974bcd95a3SBarry Smith PetscTryMethod(ksp,"KSPGMRESSetRestart_C",(KSP,PetscInt),(ksp,restart)); 3984bcd95a3SBarry Smith PetscFunctionReturn(PETSC_SUCCESS); 3994bcd95a3SBarry Smith} 4004bcd95a3SBarry Smith``` 4014bcd95a3SBarry Smith 4024bcd95a3SBarry SmithThe `Try` variant skips the function call if the method has not been composed with 4034bcd95a3SBarry Smiththe object while the `Use` version generates an error in that case. 4044bcd95a3SBarry SmithSee also, `PetscUseTypeMethod()`, and `PetscTryTypeMethod()`. 4054bcd95a3SBarry Smith 4064bcd95a3SBarry Smith### Simple PETSc Objects 4074bcd95a3SBarry Smith 4084bcd95a3SBarry SmithSome simple PETSc objects do not need `PETSCHEADER` and the associated 4094bcd95a3SBarry Smithfunctionality. These objects are internally named as `_n_<class>` as 4104bcd95a3SBarry Smithopposed to `_p_<class>`, for example, `_n_PetscFunctionList` vs `_p_Vec`. 4114bcd95a3SBarry Smith 4124bcd95a3SBarry Smith## PETSc Packages 4134bcd95a3SBarry Smith 4144bcd95a3SBarry SmithThe PETSc source code is divided into the following library-level 4154bcd95a3SBarry Smithpackages: `Sys`, `Vec`, `Mat`, `DM`, `KSP`, `SNES`, `TS`, 4164bcd95a3SBarry Smith`Tao`. Each of these has a directory under the `src` directory in 4174bcd95a3SBarry Smiththe PETSc tree and, optionally, can be compiled into separate libraries. 4184bcd95a3SBarry SmithEach package defines one or more classes; for example, the `KSP` 4194bcd95a3SBarry Smithpackage defines the `KSP` and `PC` classes, as well as several 4204bcd95a3SBarry Smithutility classes. In addition, each library-level package may contain 4214bcd95a3SBarry Smithseveral class-level packages associated with individual classes in the 4224bcd95a3SBarry Smithlibrary-level package. In general, most “important” classes in PETSc 4234bcd95a3SBarry Smithhave their own class level package. Each package provides a registration 4244bcd95a3SBarry Smithfunction `XXXInitializePackage()`, for example 4254bcd95a3SBarry Smith`KSPInitializePackage()`, which registers all the classes and events 4264bcd95a3SBarry Smithfor that package. Each package also registers a finalization routine, 4274bcd95a3SBarry Smith`XXXFinalizePackage()`, that releases all the resources used in 4284bcd95a3SBarry Smithregistering the package, using `PetscRegisterFinalize()`. The 4294bcd95a3SBarry Smithregistration for each package is performed “on demand” the first time a 4304bcd95a3SBarry Smithclass in the package is utilized. This is handled, for example, with 4314bcd95a3SBarry Smithcode such as 4324bcd95a3SBarry Smith 4334bcd95a3SBarry Smith``` 4344bcd95a3SBarry SmithPetscErrorCode VecCreate(MPI_Comm comm, Vec *vec) 4354bcd95a3SBarry Smith{ 4364bcd95a3SBarry Smith Vec v; 4374bcd95a3SBarry Smith 4384bcd95a3SBarry Smith PetscFunctionBegin; 4394bcd95a3SBarry Smith PetscAssertPointer(vec,2); 4404bcd95a3SBarry Smith *vec = NULL; 4414bcd95a3SBarry Smith VecInitializePackage(); 4424bcd95a3SBarry Smith ... 4434bcd95a3SBarry Smith``` 444