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