xref: /petsc/src/binding/petsc4py/src/petsc4py/PETSc/Object.pyx (revision 5574ef43b0ac3357bb9db30b381e3fae1c24bab1)
1# --------------------------------------------------------------------
2
3cdef class Object:
4    """Base class wrapping a PETSc object.
5
6    See Also
7    --------
8    petsc.PetscObject
9
10    """
11    # --- special methods ---
12
13    def __cinit__(self):
14        self.oval = NULL
15        self.obj = &self.oval
16
17    def __dealloc__(self):
18        CHKERR(PetscDEALLOC(&self.obj[0]))
19        self.obj = NULL
20
21    def __richcmp__(self, other, int op):
22        if not isinstance(self,  Object): return NotImplemented
23        if not isinstance(other, Object): return NotImplemented
24        cdef Object s = self, o = other
25        if   op == 2: return (s.obj[0] == o.obj[0])
26        elif op == 3: return (s.obj[0] != o.obj[0])
27        else: raise TypeError("only '==' and '!='")
28
29    def __bool__(self):
30        return self.obj[0] != NULL
31
32    def __copy__(self):
33        cdef Object obj = type(self)()
34        cdef PetscObject o = self.obj[0]
35        if o != NULL:
36            CHKERR(PetscObjectReference(o))
37        obj.obj[0] = o
38        return obj
39
40    def __deepcopy__(self, dict memo):
41        cdef object obj_copy = None
42        try:
43            obj_copy = self.copy
44        except AttributeError:
45            raise NotImplementedError
46        <void>memo # unused
47        return obj_copy()
48
49    # --- attribute management ---
50
51    cdef object get_attr(self, char name[]):
52        return PetscGetPyObj(self.obj[0], name)
53
54    cdef object set_attr(self, char name[], object attr):
55        return PetscSetPyObj(self.obj[0], name, attr)
56
57    cdef object get_dict(self):
58        return PetscGetPyDict(self.obj[0], True)
59
60    #
61
62    def view(self, Viewer viewer=None) -> None:
63        """Display the object.
64
65        Collective.
66
67        Parameters
68        ----------
69        viewer
70            A `Viewer` instance or `None` for the default viewer.
71
72        See Also
73        --------
74        petsc.PetscObjectView
75
76        """
77        cdef PetscViewer vwr = NULL
78        if viewer is not None: vwr = viewer.vwr
79        CHKERR(PetscObjectView(self.obj[0], vwr))
80
81    def destroy(self) -> Self:
82        """Destroy the object.
83
84        Collective.
85
86        See Also
87        --------
88        petsc.PetscObjectDestroy
89
90        """
91        CHKERR(PetscObjectDestroy(&self.obj[0]))
92        return self
93
94    def getType(self) -> str:
95        """Return the object type name.
96
97        Not collective.
98
99        See Also
100        --------
101        petsc.PetscObjectGetType
102
103        """
104        cdef const char *cval = NULL
105        CHKERR(PetscObjectGetType(self.obj[0], &cval))
106        return bytes2str(cval)
107
108    #
109
110    def setOptionsPrefix(self, prefix : str | None) -> None:
111        """Set the prefix used for searching for options in the database.
112
113        Logically collective.
114
115        See Also
116        --------
117        petsc_options, getOptionsPrefix, petsc.PetscObjectSetOptionsPrefix
118
119        """
120        cdef const char *cval = NULL
121        prefix = str2bytes(prefix, &cval)
122        CHKERR(PetscObjectSetOptionsPrefix(self.obj[0], cval))
123
124    def getOptionsPrefix(self) -> str:
125        """Return the prefix used for searching for options in the database.
126
127        Not collective.
128
129        See Also
130        --------
131        petsc_options, setOptionsPrefix, petsc.PetscObjectGetOptionsPrefix
132
133        """
134        cdef const char *cval = NULL
135        CHKERR(PetscObjectGetOptionsPrefix(self.obj[0], &cval))
136        return bytes2str(cval)
137
138    def appendOptionsPrefix(self, prefix: str | None) -> None:
139        """Append to the prefix used for searching for options in the database.
140
141        Logically collective.
142
143        See Also
144        --------
145        petsc_options, setOptionsPrefix, petsc.PetscObjectAppendOptionsPrefix
146
147        """
148        cdef const char *cval = NULL
149        prefix = str2bytes(prefix, &cval)
150        CHKERR(PetscObjectAppendOptionsPrefix(self.obj[0], cval))
151
152    def setFromOptions(self) -> None:
153        """Configure the object from the options database.
154
155        Collective.
156
157        Classes that do not implement ``setFromOptions`` use this method
158        that, in turn, calls `petsc.PetscObjectSetFromOptions`.
159
160        See Also
161        --------
162        petsc_options, petsc.PetscObjectSetFromOptions
163
164        """
165        CHKERR(PetscObjectSetFromOptions(self.obj[0]))
166
167    def viewFromOptions(self, name : str, Object objpre=None) -> None:
168        """View the object via command line options.
169
170        Collective.
171
172        Parameters
173        ----------
174        name
175            The command line option.
176        objpre
177            Optional object that provides prefix.
178
179        See Also
180        --------
181        petsc_options, petsc.PetscObjectViewFromOptions
182
183        """
184        cdef PetscObject pobj = NULL
185        cdef const char *cval = NULL
186        pobj = objpre.obj[0] if objpre is not None else NULL
187        name = str2bytes(name, &cval)
188        CHKERR(PetscObjectViewFromOptions(self.obj[0], pobj, cval))
189
190    def setOptionsHandler(self, handler: PetscOptionsHandlerFunction | None) -> None:
191        """Set the callback for processing extra options.
192
193        Logically collective.
194
195        Parameters
196        ----------
197        handler
198            The callback function, called at the end of a ``setFromOptions`` invocation
199            for the given class.
200
201        See Also
202        --------
203        petsc_options, Mat.setFromOptions, KSP.setFromOptions
204        petsc.PetscObjectAddOptionsHandler
205
206        """
207        if handler is not None:
208            CHKERR(PetscObjectAddOptionsHandler(self.obj[0], PetscObjectOptionsHandler_PYTHON, NULL, NULL))
209            self.set_attr('__optshandler__', handler)
210        else:
211            self.set_attr('__optshandler__', None)
212
213    def destroyOptionsHandlers(self) -> None:
214        """Clear all the option handlers.
215
216        Collective.
217
218        See Also
219        --------
220        petsc_options, setOptionsHandler, petsc.PetscObjectDestroyOptionsHandlers
221
222        """
223        self.set_attr('__optshandler__', None)
224        CHKERR(PetscObjectDestroyOptionsHandlers(self.obj[0]))
225
226    #
227
228    def getComm(self) -> Comm:
229        """Return the communicator of the object.
230
231        Not collective.
232
233        See Also
234        --------
235        petsc.PetscObjectGetComm
236
237        """
238        cdef Comm comm = Comm()
239        CHKERR(PetscObjectGetComm(self.obj[0], &comm.comm))
240        return comm
241
242    def getName(self) -> str:
243        """Return the name of the object.
244
245        Not collective.
246
247        See Also
248        --------
249        petsc.PetscObjectGetName
250
251        """
252        cdef const char *cval = NULL
253        CHKERR(PetscObjectGetName(self.obj[0], &cval))
254        return bytes2str(cval)
255
256    def setName(self, name : str | None) -> None:
257        """Associate a name to the object.
258
259        Not collective.
260
261        See Also
262        --------
263        petsc.PetscObjectSetName
264
265        """
266        cdef const char *cval = NULL
267        name = str2bytes(name, &cval)
268        CHKERR(PetscObjectSetName(self.obj[0], cval))
269
270    def getClassId(self) -> int:
271        """Return the class identifier of the object.
272
273        Not collective.
274
275        See Also
276        --------
277        petsc.PetscObjectGetClassId
278
279        """
280        cdef PetscClassId classid = 0
281        CHKERR(PetscObjectGetClassId(self.obj[0], &classid))
282        return <long>classid
283
284    def getClassName(self) -> str:
285        """Return the class name of the object.
286
287        Not collective.
288
289        See Also
290        --------
291        petsc.PetscObjectGetClassName
292
293        """
294        cdef const char *cval = NULL
295        CHKERR(PetscObjectGetClassName(self.obj[0], &cval))
296        return bytes2str(cval)
297
298    def getRefCount(self) -> int:
299        """Return the reference count of the object.
300
301        Not collective.
302
303        See Also
304        --------
305        petsc.PetscObjectGetReference
306
307        """
308        if self.obj[0] == NULL: return 0
309        cdef PetscInt refcnt = 0
310        CHKERR(PetscObjectGetReference(self.obj[0], &refcnt))
311        return toInt(refcnt)
312
313    def getId(self) -> int:
314        """Return the unique identifier of the object.
315
316        Not collective.
317
318        See Also
319        --------
320        petsc.PetscObjectGetId
321
322        """
323        cdef PetscObjectId cid = 0
324        CHKERR(PetscObjectGetId(self.obj[0], &cid))
325        return <long>cid
326
327    # --- general support ---
328
329    def compose(self, name : str | None, Object obj or None) -> None:
330        """Associate a PETSc object using a key string.
331
332        Logically collective.
333
334        Parameters
335        ----------
336        name
337            The string identifying the object to be composed.
338        obj
339            The object to be composed.
340
341        See Also
342        --------
343        query, petsc.PetscObjectCompose
344
345        """
346        cdef const char *cval = NULL
347        cdef PetscObject cobj = NULL
348        name = str2bytes(name, &cval)
349        if obj is not None: cobj = obj.obj[0]
350        CHKERR(PetscObjectCompose(self.obj[0], cval, cobj))
351
352    def query(self, name: str) -> Object:
353        """Query for the PETSc object associated with a key string.
354
355        Not collective.
356
357        See Also
358        --------
359        compose, petsc.PetscObjectQuery
360
361        """
362        cdef const char *cval = NULL
363        cdef PetscObject cobj = NULL
364        name = str2bytes(name, &cval)
365        CHKERR(PetscObjectQuery(self.obj[0], cval, &cobj))
366        if cobj == NULL: return None
367        cdef Object obj = subtype_Object(cobj)()
368        obj.obj[0] = cobj
369        CHKERR(PetscINCREF(obj.obj))
370        return obj
371
372    def incRef(self) -> int:
373        """Increment the object reference count.
374
375        Logically collective.
376
377        See Also
378        --------
379        getRefCount, petsc.PetscObjectReference
380
381        """
382        cdef PetscObject obj = self.obj[0]
383        cdef PetscInt refct = 0
384        if obj != NULL:
385            CHKERR(PetscObjectReference(obj))
386            CHKERR(PetscObjectGetReference(obj, &refct))
387        return toInt(refct)
388
389    def decRef(self) -> int:
390        """Decrement the object reference count.
391
392        Logically collective.
393
394        See Also
395        --------
396        getRefCount, petsc.PetscObjectDereference
397
398        """
399        cdef PetscObject obj = self.obj[0]
400        cdef PetscInt refct = 0
401        if obj != NULL:
402            CHKERR(PetscObjectGetReference(obj, &refct))
403            CHKERR(PetscObjectDereference(obj))
404            if refct == 1: self.obj[0] = NULL
405            refct -= 1
406        return toInt(refct)
407
408    def getAttr(self, name : str) -> object:
409        """Return the attribute associated with a given name.
410
411        Not collective.
412
413        See Also
414        --------
415        setAttr, getDict
416
417        """
418        cdef const char *cval = NULL
419        name = str2bytes(name, &cval)
420        return self.get_attr(<char*>cval)
421
422    def setAttr(self, name : str, attr : object) -> None:
423        """Set an the attribute associated with a given name.
424
425        Not collective.
426
427        See Also
428        --------
429        getAttr, getDict
430
431        """
432        cdef const char *cval = NULL
433        name = str2bytes(name, &cval)
434        self.set_attr(<char*>cval, attr)
435
436    def getDict(self) -> dict:
437        """Return the dictionary of attributes.
438
439        Not collective.
440
441        See Also
442        --------
443        setAttr, getAttr
444
445        """
446        return self.get_dict()
447
448    # --- state manipulation ---
449
450    def stateIncrease(self) -> None:
451        """Increment the PETSc object state.
452
453        Logically collective.
454
455        See Also
456        --------
457        stateGet, stateSet, petsc.PetscObjectStateIncrease
458
459        """
460        PetscINCSTATE(self.obj)
461
462    def stateGet(self) -> int:
463        """Return the PETSc object state.
464
465        Not collective.
466
467        See Also
468        --------
469        stateSet, stateIncrease, petsc.PetscObjectStateGet
470
471        """
472        cdef PetscObjectState state = 0
473        CHKERR(PetscObjectStateGet(self.obj[0], &state))
474        return <long>state
475
476    def stateSet(self, state : int) -> None:
477        """Set the PETSc object state.
478
479        Logically collective.
480
481        See Also
482        --------
483        stateIncrease, stateGet, petsc.PetscObjectStateSet
484
485        """
486        cdef PetscObjectState cstate = asInt(state)
487        CHKERR(PetscObjectStateSet(self.obj[0], cstate))
488
489    # --- tab level ---
490
491    def incrementTabLevel(self, tab : int, Object parent=None) -> None:
492        """Increment the PETSc object tab level.
493
494        Logically collective.
495
496        See Also
497        --------
498        setTabLevel, getTabLevel, petsc.PetscObjectIncrementTabLevel
499
500        """
501        cdef PetscInt ctab = asInt(tab)
502        cdef PetscObject cobj = <PetscObject> NULL if parent is None else parent.obj[0]
503        CHKERR(PetscObjectIncrementTabLevel(self.obj[0], cobj, ctab))
504
505    def setTabLevel(self, level : int) -> None:
506        """Set the PETSc object tab level.
507
508        Logically collective.
509
510        See Also
511        --------
512        incrementTabLevel, getTabLevel, petsc.PetscObjectSetTabLevel
513
514        """
515        cdef PetscInt clevel = asInt(level)
516        CHKERR(PetscObjectSetTabLevel(self.obj[0], clevel))
517
518    def getTabLevel(self) -> None:
519        """Return the PETSc object tab level.
520
521        Not collective.
522
523        See Also
524        --------
525        setTabLevel, incrementTabLevel, petsc.PetscObjectGetTabLevel
526
527        """
528        cdef PetscInt clevel = 0
529        CHKERR(PetscObjectGetTabLevel(self.obj[0], &clevel))
530        return toInt(clevel)
531
532    # --- properties ---
533
534    property type:
535        """Object type."""
536        def __get__(self) -> str:
537            return self.getType()
538
539        def __set__(self, value):
540            self.setType(value)
541
542    property prefix:
543        """Options prefix."""
544        def __get__(self) -> str:
545            return self.getOptionsPrefix()
546
547        def __set__(self, value):
548            self.setOptionsPrefix(value)
549
550    property comm:
551        """The object communicator."""
552        def __get__(self) -> Comm:
553            return self.getComm()
554
555    property name:
556        """The object name."""
557        def __get__(self) -> str:
558            return self.getName()
559
560        def __set__(self, value):
561            self.setName(value)
562
563    property classid:
564        """The class identifier."""
565        def __get__(self) -> int:
566            return self.getClassId()
567
568    property id:
569        """The object identifier."""
570        def __get__(self) -> int:
571            return self.getId()
572
573    property klass:
574        """The class name."""
575        def __get__(self) -> str:
576            return self.getClassName()
577
578    property refcount:
579        """Reference count."""
580        def __get__(self) -> int:
581            return self.getRefCount()
582
583    # --- ctypes support  ---
584
585    property handle:
586        """Handle for ctypes support."""
587        def __get__(self) -> int:
588            cdef PetscObject obj = self.obj[0]
589            return PyLong_FromVoidPtr(<void*>obj)
590
591    # --- Fortran support  ---
592
593    property fortran:
594        """Fortran handle."""
595        def __get__(self) -> int:
596            cdef PetscObject obj = self.obj[0]
597            return Object_toFortran(obj)
598
599# --------------------------------------------------------------------
600
601include "cyclicgc.pxi"
602
603cdef dict type_registry = {0 : None}
604__type_registry__ = type_registry
605
606cdef int PyPetscType_Register(int classid, type cls) except -1:
607    global type_registry
608    cdef object key = <long>classid
609    cdef object value = cls
610    cdef const char *dummy = NULL
611    if key not in type_registry:
612        type_registry[key] = cls
613        reg_LogClass(str2bytes(cls.__name__, &dummy),
614                     <PetscLogClass>classid)
615        TypeEnableGC(<PyTypeObject*>cls)
616    else:
617        value = type_registry[key]
618        if cls is not value:
619            raise ValueError(
620                "key: %d, cannot register: %s, "
621                "already registered: %s" % (key, cls, value))
622    return 0
623
624cdef type PyPetscType_Lookup(int classid):
625    global type_registry
626    cdef object key = <long>classid
627    cdef type cls = Object
628    try:
629        cls = type_registry[key]
630    except KeyError:
631        cls = Object
632    return cls
633
634# --------------------------------------------------------------------
635