xref: /petsc/src/binding/petsc4py/src/petsc4py/PETSc/Section.pyx (revision 5dafb6f581977b074a43082461f4a734d7d3976b)
1# --------------------------------------------------------------------
2
3cdef class Section(Object):
4    """Mapping from integers in a range to unstructured set of integers."""
5
6    def __cinit__(self):
7        self.obj = <PetscObject*> &self.sec
8        self.sec  = NULL
9
10    def view(self, Viewer viewer=None) -> None:
11        """View the section.
12
13        Collective.
14
15        Parameters
16        ----------
17        viewer
18            A `Viewer` to display the section.
19
20        See Also
21        --------
22        petsc.PetscSectionView
23
24        """
25        cdef PetscViewer vwr = NULL
26        if viewer is not None: vwr = viewer.vwr
27        CHKERR(PetscSectionView(self.sec, vwr))
28
29    def destroy(self) -> Self:
30        """Destroy a section.
31
32        Not collective.
33
34        See Also
35        --------
36        petsc.PetscSectionDestroy
37
38        """
39        CHKERR(PetscSectionDestroy(&self.sec))
40        return self
41
42    def create(self, comm: Comm | None = None) -> Self:
43        """Allocate a section and set the map contents to the default.
44
45        Collective.
46
47        Typical calling sequence:
48        - `create`
49        - `setNumFields`
50        - `setChart`
51        - `setDof`
52        - `setUp`
53        - `getOffset`
54        - `destroy`
55
56        The `Section` object and methods are intended to be used in the PETSc
57        Vec and Mat implementations. The indices returned by the `Section` are
58        appropriate for the kind of `Vec` it is associated with. For example,
59        if the vector being indexed is a local vector, we call the section a
60        local section. If the section indexes a global vector, we call it a
61        global section. For parallel vectors, like global vectors, we use
62        negative indices to indicate DOFs owned by other processes.
63
64        Parameters
65        ----------
66        comm
67            MPI communicator, defaults to `Sys.getDefaultComm`.
68
69        See Also
70        --------
71        petsc.PetscSectionCreate
72
73        """
74        cdef MPI_Comm ccomm = def_Comm(comm, PETSC_COMM_DEFAULT)
75        cdef PetscSection newsec = NULL
76        CHKERR(PetscSectionCreate(ccomm, &newsec))
77        CHKERR(PetscCLEAR(self.obj)); self.sec = newsec
78        return self
79
80    def clone(self) -> Section:
81        """Return a copy of the section.
82
83        Collective.
84
85        The copy is shallow, if possible.
86
87        See Also
88        --------
89        petsc.PetscSectionClone
90
91        """
92        cdef Section sec = <Section>type(self)()
93        CHKERR(PetscSectionClone(self.sec, &sec.sec))
94        return sec
95
96    def setUp(self) -> None:
97        """Calculate offsets.
98
99        Not collective.
100
101        Offsets are based on the number of degrees of freedom for each point.
102
103        See Also
104        --------
105        petsc.PetscSectionSetUp
106
107        """
108        CHKERR(PetscSectionSetUp(self.sec))
109
110    def reset(self) -> None:
111        """Free all section data.
112
113        Not collective.
114
115        See Also
116        --------
117        petsc.PetscSectionReset
118
119        """
120        CHKERR(PetscSectionReset(self.sec))
121
122    def getNumFields(self) -> int:
123        """Return the number of fields in a section.
124
125        Not collective.
126
127        Returns ``0`` if no fields were defined.
128
129        See Also
130        --------
131        setNumFields, petsc.PetscSectionGetNumFields
132
133        """
134        cdef PetscInt numFields = 0
135        CHKERR(PetscSectionGetNumFields(self.sec, &numFields))
136        return toInt(numFields)
137
138    def setNumFields(self, numFields: int) -> None:
139        """Set the number of fields in a section.
140
141        Not collective.
142
143        Parameters
144        ----------
145        numFields
146            The number of fields.
147
148        See Also
149        --------
150        getNumFields, petsc.PetscSectionSetNumFields
151
152        """
153        cdef PetscInt cnumFields = asInt(numFields)
154        CHKERR(PetscSectionSetNumFields(self.sec, cnumFields))
155
156    def getFieldName(self, field: int) -> str:
157        """Return the name of a field in the section.
158
159        Not collective.
160
161        Parameters
162        ----------
163        field
164            The field number.
165
166        See Also
167        --------
168        setFieldName, petsc.PetscSectionGetFieldName
169
170        """
171        cdef PetscInt cfield = asInt(field)
172        cdef const char *fieldName = NULL
173        CHKERR(PetscSectionGetFieldName(self.sec, cfield, &fieldName))
174        return bytes2str(fieldName)
175
176    def setFieldName(self, field: int, fieldName: str) -> None:
177        """Set the name of a field in the section.
178
179        Not collective.
180
181        Parameters
182        ----------
183        field
184            The field number.
185        fieldName
186            The field name.
187
188        See Also
189        --------
190        getFieldName, petsc.PetscSectionSetFieldName
191
192        """
193        cdef PetscInt cfield = asInt(field)
194        cdef const char *cname = NULL
195        fieldName = str2bytes(fieldName, &cname)
196        CHKERR(PetscSectionSetFieldName(self.sec, cfield, cname))
197
198    def getFieldComponents(self, field: int) -> int:
199        """Return the number of field components for the given field.
200
201        Not collective.
202
203        Parameters
204        ----------
205        field
206            The field number.
207
208        See Also
209        --------
210        setFieldComponents, petsc.PetscSectionGetFieldComponents
211
212        """
213        cdef PetscInt cfield = asInt(field), cnumComp = 0
214        CHKERR(PetscSectionGetFieldComponents(self.sec, cfield, &cnumComp))
215        return toInt(cnumComp)
216
217    def setFieldComponents(self, field: int, numComp: int) -> None:
218        """Set the number of field components for the given field.
219
220        Not collective.
221
222        Parameters
223        ----------
224        field
225            The field number.
226        numComp
227            The number of field components.
228
229        See Also
230        --------
231        getFieldComponents, petsc.PetscSectionSetFieldComponents
232
233        """
234        cdef PetscInt cfield = asInt(field)
235        cdef PetscInt cnumComp = asInt(numComp)
236        CHKERR(PetscSectionSetFieldComponents(self.sec, cfield, cnumComp))
237
238    def getChart(self) -> tuple[int, int]:
239        """Return the range in which points (indices) lie for this section.
240
241        Not collective.
242
243        The range is [pStart, pEnd), i.e., from the first point to one past the
244        last point.
245
246        See Also
247        --------
248        petsc.PetscSectionGetChart
249
250        """
251        cdef PetscInt pStart = 0, pEnd = 0
252        CHKERR(PetscSectionGetChart(self.sec, &pStart, &pEnd))
253        return toInt(pStart), toInt(pEnd)
254
255    def setChart(self, pStart: int, pEnd: int) -> None:
256        """Set the range in which points (indices) lie for this section.
257
258        Not collective.
259
260        The range is [pStart, pEnd), i.e., from the first point to one past the
261        last point.
262
263        Parameters
264        ----------
265        pStart
266            The first point.
267        pEnd
268            One past the last point.
269
270        See Also
271        --------
272        petsc.PetscSectionSetChart
273
274        """
275        cdef PetscInt cStart = asInt(pStart)
276        cdef PetscInt cEnd   = asInt(pEnd)
277        CHKERR(PetscSectionSetChart(self.sec, cStart, cEnd))
278
279    def getPermutation(self) -> IS:
280        """Return the permutation that was set with `setPermutation`.
281
282        Not collective.
283
284        See Also
285        --------
286        setPermutation, petsc.PetscSectionGetPermutation
287
288        """
289        cdef IS perm = IS()
290        CHKERR(PetscSectionGetPermutation(self.sec, &perm.iset))
291        CHKERR(PetscINCREF(perm.obj))
292        return perm
293
294    def setPermutation(self, IS perm) -> None:
295        """Set the permutation for [0, pEnd - pStart).
296
297        Not collective.
298
299        Parameters
300        ----------
301        perm
302            The permutation of points.
303
304        See Also
305        --------
306        getPermutation, petsc.PetscSectionSetPermutation
307
308        """
309        CHKERR(PetscSectionSetPermutation(self.sec, perm.iset))
310
311    def getDof(self, point: int) -> int:
312        """Return the number of degrees of freedom for a given point.
313
314        Not collective.
315
316        In a global section, this value will be negative for points not owned
317        by this process.
318
319        Parameters
320        ----------
321        point
322            The point.
323
324        See Also
325        --------
326        setDof, addDof, petsc.PetscSectionGetDof
327
328        """
329        cdef PetscInt cpoint = asInt(point), cnumDof = 0
330        CHKERR(PetscSectionGetDof(self.sec, cpoint, &cnumDof))
331        return toInt(cnumDof)
332
333    def setDof(self, point: int, numDof: int) -> None:
334        """Set the number of degrees of freedom associated with a given point.
335
336        Not collective.
337
338        Parameters
339        ----------
340        point
341            The point.
342        numDof
343            The number of DOFs.
344
345        See Also
346        --------
347        getDof, addDof, petsc.PetscSectionSetDof
348
349        """
350        cdef PetscInt cpoint = asInt(point)
351        cdef PetscInt cnumDof = asInt(numDof)
352        CHKERR(PetscSectionSetDof(self.sec, cpoint, cnumDof))
353
354    def addDof(self, point: int, numDof: int) -> None:
355        """Add ``numDof`` degrees of freedom associated with a given point.
356
357        Not collective.
358
359        Parameters
360        ----------
361        point
362            The point.
363        numDof
364            The number of additional DOFs.
365
366        See Also
367        --------
368        setDof, getDof, petsc.PetscSectionAddDof
369
370        """
371        cdef PetscInt cpoint = asInt(point)
372        cdef PetscInt cnumDof = asInt(numDof)
373        CHKERR(PetscSectionAddDof(self.sec, cpoint, cnumDof))
374
375    def getFieldDof(self, point: int, field: int) -> int:
376        """Return the number of DOFs associated with a field on a given point.
377
378        Not collective.
379
380        Parameters
381        ----------
382        point
383            The point.
384        field
385            The field.
386
387        See Also
388        --------
389        setFieldDof, petsc.PetscSectionGetFieldDof
390
391        """
392        cdef PetscInt cpoint = asInt(point), cnumDof = 0
393        cdef PetscInt cfield = asInt(field)
394        CHKERR(PetscSectionGetFieldDof(self.sec, cpoint, cfield, &cnumDof))
395        return toInt(cnumDof)
396
397    def setFieldDof(self, point: int, field: int, numDof: int) -> None:
398        """Set the number of DOFs associated with a field on a given point.
399
400        Not collective.
401
402        Parameters
403        ----------
404        point
405            The point.
406        field
407            The field.
408        numDof
409            The number of DOFs.
410
411        See Also
412        --------
413        getFieldDof, addFieldDof, petsc.PetscSectionSetFieldDof
414
415        """
416        cdef PetscInt cpoint = asInt(point)
417        cdef PetscInt cfield = asInt(field)
418        cdef PetscInt cnumDof = asInt(numDof)
419        CHKERR(PetscSectionSetFieldDof(self.sec, cpoint, cfield, cnumDof))
420
421    def addFieldDof(self, point: int, field: int, numDof: int) -> None:
422        """Add ``numDof`` DOFs associated with a field on a given point.
423
424        Not collective.
425
426        Parameters
427        ----------
428        point
429            The point.
430        field
431            The field.
432        numDof
433            The number of additional DOFs.
434
435        See Also
436        --------
437        setFieldDof, getFieldDof, petsc.PetscSectionAddFieldDof
438
439        """
440        cdef PetscInt cpoint = asInt(point)
441        cdef PetscInt cfield = asInt(field)
442        cdef PetscInt cnumDof = asInt(numDof)
443        CHKERR(PetscSectionAddFieldDof(self.sec, cpoint, cfield, cnumDof))
444
445    def getConstraintDof(self, point: int) -> int:
446        """Return the number of constrained DOFs associated with a given point.
447
448        Not collective.
449
450        Parameters
451        ----------
452        point
453            The point.
454
455        See Also
456        --------
457        setConstraintDof, petsc.PetscSectionGetConstraintDof
458
459        """
460        cdef PetscInt cpoint = asInt(point), cnumDof = 0
461        CHKERR(PetscSectionGetConstraintDof(self.sec, cpoint, &cnumDof))
462        return toInt(cnumDof)
463
464    def setConstraintDof(self, point: int, numDof: int) -> None:
465        """Set the number of constrained DOFs associated with a given point.
466
467        Not collective.
468
469        Parameters
470        ----------
471        point
472            The point.
473        numDof
474            The number of DOFs which are fixed by constraints.
475
476        See Also
477        --------
478        getConstraintDof, addConstraintDof, petsc.PetscSectionSetConstraintDof
479
480        """
481        cdef PetscInt cpoint = asInt(point)
482        cdef PetscInt cnumDof = asInt(numDof)
483        CHKERR(PetscSectionSetConstraintDof(self.sec, cpoint, cnumDof))
484
485    def addConstraintDof(self, point: int, numDof: int) -> None:
486        """Increment the number of constrained DOFs for a given point.
487
488        Not collective.
489
490        Parameters
491        ----------
492        point
493            The point.
494        numDof
495            The number of additional DOFs which are fixed by constraints.
496
497        See Also
498        --------
499        setConstraintDof, getConstraintDof, petsc.PetscSectionAddConstraintDof
500
501        """
502        cdef PetscInt cpoint = asInt(point)
503        cdef PetscInt cnumDof = asInt(numDof)
504        CHKERR(PetscSectionAddConstraintDof(self.sec, cpoint, cnumDof))
505
506    def getFieldConstraintDof(self, point: int, field: int) -> int:
507        """Return the number of constrained DOFs for a given field on a point.
508
509        Not collective.
510
511        Parameters
512        ----------
513        point
514            The point.
515        field
516            The field.
517
518        See Also
519        --------
520        setFieldConstraintDof, petsc.PetscSectionGetFieldConstraintDof
521
522        """
523        cdef PetscInt cpoint = asInt(point), cnumDof = 0
524        cdef PetscInt cfield = asInt(field)
525        CHKERR(PetscSectionGetFieldConstraintDof(self.sec, cpoint, cfield, &cnumDof))
526        return toInt(cnumDof)
527
528    def setFieldConstraintDof(
529        self,
530        point: int,
531        field: int,
532        numDof: int) -> None:
533        """Set the number of constrained DOFs for a given field on a point.
534
535        Not collective.
536
537        Parameters
538        ----------
539        point
540            The point.
541        field
542            The field.
543        numDof
544            The number of DOFs which are fixed by constraints.
545
546        See Also
547        --------
548        getFieldConstraintDof, addFieldConstraintDof
549        petsc.PetscSectionSetFieldConstraintDof
550
551        """
552        cdef PetscInt cpoint = asInt(point)
553        cdef PetscInt cfield = asInt(field)
554        cdef PetscInt cnumDof = asInt(numDof)
555        CHKERR(PetscSectionSetFieldConstraintDof(self.sec, cpoint, cfield, cnumDof))
556
557    def addFieldConstraintDof(
558        self,
559        point: int,
560        field: int,
561        numDof: int) -> None:
562        """Add ``numDof`` constrained DOFs for a given field on a point.
563
564        Not collective.
565
566        Parameters
567        ----------
568        point
569            The point.
570        field
571            The field.
572        numDof
573            The number of additional DOFs which are fixed by constraints.
574
575        See Also
576        --------
577        setFieldConstraintDof, getFieldConstraintDof
578        petsc.PetscSectionAddFieldConstraintDof
579
580        """
581        cdef PetscInt cpoint = asInt(point)
582        cdef PetscInt cfield = asInt(field)
583        cdef PetscInt cnumDof = asInt(numDof)
584        CHKERR(PetscSectionAddFieldConstraintDof(self.sec, cpoint, cfield, cnumDof))
585
586    def getConstraintIndices(self, point: int) -> ArrayInt:
587        """Return the point DOFs numbers which are constrained for a given point.
588
589        Not collective.
590
591        The range is in [0, DOFs).
592
593        Parameters
594        ----------
595        point
596            The point.
597
598        See Also
599        --------
600        setConstraintIndices, petsc.PetscSectionGetConstraintIndices
601
602        """
603        cdef PetscInt cpoint = asInt(point)
604        cdef PetscInt nindex = 0
605        cdef const PetscInt *indices = NULL
606        CHKERR(PetscSectionGetConstraintDof(self.sec, cpoint, &nindex))
607        CHKERR(PetscSectionGetConstraintIndices(self.sec, cpoint, &indices))
608        return array_i(nindex, indices)
609
610    def setConstraintIndices(self, point: int, indices: Sequence[int]) -> None:
611        """Set the point DOFs numbers, in [0, DOFs), which are constrained.
612
613        Not collective.
614
615        Parameters
616        ----------
617        point
618            The point.
619        indices
620            The constrained DOFs.
621
622        See Also
623        --------
624        getConstraintIndices, petsc.PetscSectionSetConstraintIndices
625
626        """
627        cdef PetscInt cpoint = asInt(point)
628        cdef PetscInt nindex = 0
629        cdef PetscInt *cindices = NULL
630        indices = iarray_i(indices, &nindex, &cindices)
631        CHKERR(PetscSectionSetConstraintDof(self.sec, cpoint, nindex))
632        CHKERR(PetscSectionSetConstraintIndices(self.sec, cpoint, cindices))
633
634    def getFieldConstraintIndices(self, point: int, field: int) -> ArrayInt:
635        """Return the field DOFs numbers, in [0, DOFs), which are constrained.
636
637        Not collective.
638
639        The constrained DOFs are sorted in ascending order.
640
641        Parameters
642        ----------
643        field
644            The field number.
645        point
646            The point.
647
648        See Also
649        --------
650        setFieldConstraintIndices, petsc.PetscSectionGetFieldConstraintIndices
651
652        """
653        cdef PetscInt cpoint = asInt(point)
654        cdef PetscInt cfield = asInt(field)
655        cdef PetscInt nindex = 0
656        cdef const PetscInt *indices = NULL
657        CHKERR(PetscSectionGetFieldConstraintDof(self.sec, cpoint, cfield, &nindex))
658        CHKERR(PetscSectionGetFieldConstraintIndices(self.sec, cpoint, cfield, &indices))
659        return array_i(nindex, indices)
660
661    def setFieldConstraintIndices(
662        self,
663        point: int,
664        field: int,
665        indices: Sequence[int]) -> None:
666        """Set the field DOFs numbers, in [0, DOFs), which are constrained.
667
668        Not collective.
669
670        Parameters
671        ----------
672        point
673            The point.
674        field
675            The field number.
676        indices
677            The constrained DOFs.
678
679        See Also
680        --------
681        getFieldConstraintIndices, petsc.PetscSectionSetFieldConstraintIndices
682
683        """
684        cdef PetscInt cpoint = asInt(point)
685        cdef PetscInt cfield = asInt(field)
686        cdef PetscInt nindex = 0
687        cdef PetscInt *cindices = NULL
688        indices = iarray_i(indices, &nindex, &cindices)
689        CHKERR(PetscSectionSetFieldConstraintDof(self.sec, cpoint, cfield, nindex))
690        CHKERR(PetscSectionSetFieldConstraintIndices(self.sec, cpoint, cfield, cindices))
691
692    def getMaxDof(self) -> int:
693        """Return the maximum number of DOFs for any point in the section.
694
695        Not collective.
696
697        See Also
698        --------
699        petsc.PetscSectionGetMaxDof
700
701        """
702        cdef PetscInt maxDof = 0
703        CHKERR(PetscSectionGetMaxDof(self.sec, &maxDof))
704        return toInt(maxDof)
705
706    def getStorageSize(self) -> int:
707        """Return the size capable of holding all the DOFs defined in a section.
708
709        Not collective.
710
711        See Also
712        --------
713        getConstrainedStorageSize, petsc.PetscSectionGetStorageSize
714
715        """
716        cdef PetscInt size = 0
717        CHKERR(PetscSectionGetStorageSize(self.sec, &size))
718        return toInt(size)
719
720    def getConstrainedStorageSize(self) -> int:
721        """Return the size capable of holding all unconstrained DOFs in a section.
722
723        Not collective.
724
725        See Also
726        --------
727        getStorageSize, petsc.PetscSectionGetConstrainedStorageSize
728
729        """
730        cdef PetscInt size = 0
731        CHKERR(PetscSectionGetConstrainedStorageSize(self.sec, &size))
732        return toInt(size)
733
734    def getOffset(self, point: int) -> int:
735        """Return the offset for the DOFs associated with the given point.
736
737        Not collective.
738
739        In a global section, this offset will be negative for points not owned
740        by this process.
741
742        Parameters
743        ----------
744        point
745            The point.
746
747        See Also
748        --------
749        setOffset, petsc.PetscSectionGetOffset
750
751        """
752        cdef PetscInt cpoint = asInt(point), offset = 0
753        CHKERR(PetscSectionGetOffset(self.sec, cpoint, &offset))
754        return toInt(offset)
755
756    def setOffset(self, point: int, offset: int) -> None:
757        """Set the offset for the DOFs associated with the given point.
758
759        Not collective.
760
761        The user usually does not call this function, but uses `setUp`.
762
763        Parameters
764        ----------
765        point
766            The point.
767        offset
768            The offset.
769
770        See Also
771        --------
772        getOffset, petsc.PetscSectionSetOffset
773
774        """
775        cdef PetscInt cpoint = asInt(point)
776        cdef PetscInt coffset = asInt(offset)
777        CHKERR(PetscSectionSetOffset(self.sec, cpoint, coffset))
778
779    def getFieldOffset(self, point: int, field: int) -> int:
780        """Return the offset for the field DOFs on the given point.
781
782        Not collective.
783
784        In a global section, this offset will be negative for points not owned
785        by this process.
786
787        Parameters
788        ----------
789        point
790            The point.
791        field
792            The field.
793
794        See Also
795        --------
796        setFieldOffset, petsc.PetscSectionGetFieldOffset
797
798        """
799        cdef PetscInt cpoint = asInt(point)
800        cdef PetscInt cfield = asInt(field)
801        cdef PetscInt offset = 0
802        CHKERR(PetscSectionGetFieldOffset(self.sec, cpoint, cfield, &offset))
803        return toInt(offset)
804
805    def setFieldOffset(self, point: int, field: int, offset: int) -> None:
806        """Set the offset for the DOFs on the given field at a point.
807
808        Not collective.
809
810        The user usually does not call this function, but uses `setUp`.
811
812        Parameters
813        ----------
814        point
815            The point.
816        field
817            The field.
818        offset
819            The offset.
820
821        See Also
822        --------
823        getFieldOffset, petsc.PetscSectionSetFieldOffset
824
825        """
826        cdef PetscInt cpoint = asInt(point)
827        cdef PetscInt cfield = asInt(field)
828        cdef PetscInt coffset = asInt(offset)
829        CHKERR(PetscSectionSetFieldOffset(self.sec, cpoint, cfield, coffset))
830
831    def getOffsetRange(self) -> tuple[int, int]:
832        """Return the full range of offsets, [start, end), for a section.
833
834        Not collective.
835
836        See Also
837        --------
838        petsc.PetscSectionGetOffsetRange
839
840        """
841        cdef PetscInt oStart = 0, oEnd = 0
842        CHKERR(PetscSectionGetOffsetRange(self.sec, &oStart, &oEnd))
843        return toInt(oStart), toInt(oEnd)
844
845    # FIXME: Hardcoded PETSC_FALSE parameters
846    def createGlobalSection(self, SF sf) -> Section:
847        """Create a section describing the global field layout.
848
849        Collective.
850
851        The section describes the global field layout using the local section
852        and an `SF` describing the section point overlap.
853
854        If we have a set of local sections defining the layout of a set of
855        local vectors, and also an `SF` to determine which section points are
856        shared and the ownership, we can calculate a global section defining
857        the parallel data layout, and the associated global vector.
858
859        This gives negative sizes and offsets to points not owned by this
860        process.
861
862        ``includeConstraints`` and ``localOffsets`` parameters of the C API
863        are always set to `False`.
864
865        Parameters
866        ----------
867        sf
868            The `SF` describing the parallel layout of the section points
869            (leaves are unowned local points).
870
871        See Also
872        --------
873        petsc.PetscSectionCreateGlobalSection
874
875        """
876        cdef Section gsec = Section()
877        CHKERR(PetscSectionCreateGlobalSection(self.sec, sf.sf, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &gsec.sec))
878        return gsec
879