xref: /libCEED/python/ceed.py (revision 777ff853944a0dbc06f7f09486fdf4674828e728)
139b2de37Sjeremylt# Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
239b2de37Sjeremylt# the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
339b2de37Sjeremylt# reserved. See files LICENSE and NOTICE for details.
439b2de37Sjeremylt#
539b2de37Sjeremylt# This file is part of CEED, a collection of benchmarks, miniapps, software
639b2de37Sjeremylt# libraries and APIs for efficient high-order finite element and spectral
739b2de37Sjeremylt# element discretizations for exascale applications. For more information and
839b2de37Sjeremylt# source code availability see http://github.com/ceed.
939b2de37Sjeremylt#
1039b2de37Sjeremylt# The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
1139b2de37Sjeremylt# a collaborative effort of two U.S. Department of Energy organizations (Office
1239b2de37Sjeremylt# of Science and the National Nuclear Security Administration) responsible for
1339b2de37Sjeremylt# the planning and preparation of a capable exascale ecosystem, including
1439b2de37Sjeremylt# software, applications, hardware, advanced system engineering and early
1539b2de37Sjeremylt# testbed platforms, in support of the nation's exascale computing imperative.
1639b2de37Sjeremylt
1739b2de37Sjeremyltfrom _ceed_cffi import ffi, lib
1839b2de37Sjeremyltimport sys
19477729cfSJeremy L Thompsonimport os
2039b2de37Sjeremyltimport io
210a0da059Sjeremyltimport tempfile
2239b2de37Sjeremyltfrom abc import ABC
2339b2de37Sjeremyltfrom .ceed_vector import Vector
2439b2de37Sjeremyltfrom .ceed_basis import BasisTensorH1, BasisTensorH1Lagrange, BasisH1
2569a53589Sjeremyltfrom .ceed_elemrestriction import ElemRestriction, StridedElemRestriction, BlockedElemRestriction, BlockedStridedElemRestriction
2639b2de37Sjeremyltfrom .ceed_qfunction import QFunction, QFunctionByName, IdentityQFunction
27*777ff853SJeremy L Thompsonfrom .ceed_qfunctioncontext import QFunctionContext
2839b2de37Sjeremyltfrom .ceed_operator import Operator, CompositeOperator
2939b2de37Sjeremyltfrom .ceed_constants import *
3039b2de37Sjeremylt
3139b2de37Sjeremylt# ------------------------------------------------------------------------------
327a7b0fa3SJed Brown
337a7b0fa3SJed Brown
3439b2de37Sjeremyltclass Ceed():
3539b2de37Sjeremylt    """Ceed: core components."""
3639b2de37Sjeremylt    # Attributes
3739b2de37Sjeremylt    _pointer = ffi.NULL
3839b2de37Sjeremylt
3939b2de37Sjeremylt    # Constructor
4039b2de37Sjeremylt    def __init__(self, resource="/cpu/self"):
4139b2de37Sjeremylt        # libCEED object
4239b2de37Sjeremylt        self._pointer = ffi.new("Ceed *")
4339b2de37Sjeremylt
4439b2de37Sjeremylt        # libCEED call
4539b2de37Sjeremylt        resourceAscii = ffi.new("char[]", resource.encode("ascii"))
46477729cfSJeremy L Thompson        os.environ["CEED_ERROR_HANDLER"] = "return"
47477729cfSJeremy L Thompson        err_code = lib.CeedInit(resourceAscii, self._pointer)
48477729cfSJeremy L Thompson        if err_code:
49477729cfSJeremy L Thompson            raise Exception("Error initializing backend resource: " + resource)
50477729cfSJeremy L Thompson        lib.CeedSetErrorHandler(
51477729cfSJeremy L Thompson            self._pointer[0], ffi.addressof(
52477729cfSJeremy L Thompson                lib, "CeedErrorStore"))
5339b2de37Sjeremylt
5439b2de37Sjeremylt    # Representation
5539b2de37Sjeremylt    def __repr__(self):
5639b2de37Sjeremylt        return "<Ceed instance at " + hex(id(self)) + ">"
5739b2de37Sjeremylt
580a0da059Sjeremylt    # String conversion for print() to stdout
590a0da059Sjeremylt    def __str__(self):
600a0da059Sjeremylt        """View a Ceed via print()."""
610a0da059Sjeremylt
620a0da059Sjeremylt        # libCEED call
630a0da059Sjeremylt        with tempfile.NamedTemporaryFile() as key_file:
640a0da059Sjeremylt            with open(key_file.name, 'r+') as stream_file:
650a0da059Sjeremylt                stream = ffi.cast("FILE *", stream_file)
660a0da059Sjeremylt
67477729cfSJeremy L Thompson                err_code = lib.CeedView(self._pointer[0], stream)
68477729cfSJeremy L Thompson                self._check_error(err_code)
690a0da059Sjeremylt
700a0da059Sjeremylt                stream_file.seek(0)
710a0da059Sjeremylt                out_string = stream_file.read()
720a0da059Sjeremylt
730a0da059Sjeremylt        return out_string
740a0da059Sjeremylt
75477729cfSJeremy L Thompson    # Error handler
76477729cfSJeremy L Thompson    def _check_error(self, err_code):
77477729cfSJeremy L Thompson        """Check return code and retrieve error message for non-zero code"""
78477729cfSJeremy L Thompson        if (err_code):
79477729cfSJeremy L Thompson            message = ffi.new("char **")
80477729cfSJeremy L Thompson            lib.CeedGetErrorMessage(self._pointer[0], message)
81477729cfSJeremy L Thompson            raise Exception(ffi.string(message[0]).decode("UTF-8"))
82477729cfSJeremy L Thompson
8339b2de37Sjeremylt    # Get Resource
8439b2de37Sjeremylt    def get_resource(self):
8539b2de37Sjeremylt        """Get the full resource name for a Ceed context.
8639b2de37Sjeremylt
8739b2de37Sjeremylt           Returns:
8839b2de37Sjeremylt             resource: resource name"""
8939b2de37Sjeremylt
9039b2de37Sjeremylt        # libCEED call
9139b2de37Sjeremylt        resource = ffi.new("char **")
92477729cfSJeremy L Thompson        err_code = lib.CeedGetResource(self._pointer[0], resource)
93477729cfSJeremy L Thompson        self._check_error(err_code)
9439b2de37Sjeremylt
9539b2de37Sjeremylt        return ffi.string(resource[0]).decode("UTF-8")
9639b2de37Sjeremylt
9739b2de37Sjeremylt    # Preferred MemType
9839b2de37Sjeremylt    def get_preferred_memtype(self):
9939b2de37Sjeremylt        """Return Ceed preferred memory type.
10039b2de37Sjeremylt
10139b2de37Sjeremylt           Returns:
10239b2de37Sjeremylt             memtype: Ceed preferred memory type"""
10339b2de37Sjeremylt
10439b2de37Sjeremylt        # libCEED call
10539b2de37Sjeremylt        memtype = ffi.new("CeedMemType *", MEM_HOST)
106477729cfSJeremy L Thompson        err_code = lib.CeedGetPreferredMemType(self._pointer[0], memtype)
107477729cfSJeremy L Thompson        self._check_error(err_code)
10839b2de37Sjeremylt
10939b2de37Sjeremylt        return memtype[0]
11039b2de37Sjeremylt
11139b2de37Sjeremylt    # CeedVector
11239b2de37Sjeremylt    def Vector(self, size):
11339b2de37Sjeremylt        """Ceed Vector: storing and manipulating vectors.
11439b2de37Sjeremylt
11539b2de37Sjeremylt           Args:
11639b2de37Sjeremylt             size: length of vector
11739b2de37Sjeremylt
11839b2de37Sjeremylt           Returns:
11939b2de37Sjeremylt             vector: Ceed Vector"""
12039b2de37Sjeremylt
12139b2de37Sjeremylt        return Vector(self, size)
12239b2de37Sjeremylt
12339b2de37Sjeremylt    # CeedElemRestriction
124d979a051Sjeremylt    def ElemRestriction(self, nelem, elemsize, ncomp, compstride, lsize, offsets,
125d979a051Sjeremylt                        memtype=lib.CEED_MEM_HOST, cmode=lib.CEED_COPY_VALUES):
12639b2de37Sjeremylt        """Ceed ElemRestriction: restriction from local vectors to elements.
12739b2de37Sjeremylt
12839b2de37Sjeremylt           Args:
129d979a051Sjeremylt             nelem: number of elements described by the restriction
13039b2de37Sjeremylt             elemsize: size (number of nodes) per element
131d979a051Sjeremylt             ncomp: number of field components per interpolation node
132d979a051Sjeremylt                      (1 for scalar fields)
133d979a051Sjeremylt             compstride: Stride between components for the same L-vector "node".
134d979a051Sjeremylt                           Data for node i, component k can be found in the
135d979a051Sjeremylt                           L-vector at index [offsets[i] + k*compstride].
136d979a051Sjeremylt             lsize: The size of the L-vector. This vector may be larger than
137d979a051Sjeremylt                       the elements and fields given by this restriction.
138d979a051Sjeremylt             *offsets: Numpy array of shape [nelem, elemsize]. Row i holds the
139d979a051Sjeremylt                         ordered list of the offsets (into the input Ceed Vector)
14039b2de37Sjeremylt                         for the unknowns corresponding to element i, where
141d979a051Sjeremylt                         0 <= i < nelem. All offsets must be in the range
142d979a051Sjeremylt                         [0, lsize - 1].
143d979a051Sjeremylt             **memtype: memory type of the offsets array, default CEED_MEM_HOST
144d979a051Sjeremylt             **cmode: copy mode for the offsets array, default CEED_COPY_VALUES
14539b2de37Sjeremylt
14639b2de37Sjeremylt           Returns:
14739b2de37Sjeremylt             elemrestriction: Ceed ElemRestiction"""
14839b2de37Sjeremylt
149d979a051Sjeremylt        return ElemRestriction(self, nelem, elemsize, ncomp, compstride, lsize,
150d979a051Sjeremylt                               offsets, memtype=memtype, cmode=cmode)
15139b2de37Sjeremylt
152d979a051Sjeremylt    def StridedElemRestriction(self, nelem, elemsize, ncomp, lsize, strides):
153d979a051Sjeremylt        """Ceed Identity ElemRestriction: strided restriction from local vectors
154d979a051Sjeremylt             to elements.
15539b2de37Sjeremylt
15639b2de37Sjeremylt           Args:
157d979a051Sjeremylt             nelem: number of elements described by the restriction
15839b2de37Sjeremylt             elemsize: size (number of nodes) per element
159a8d32208Sjeremylt             ncomp: number of field components per interpolation node
160a8d32208Sjeremylt                      (1 for scalar fields)
161d979a051Sjeremylt             lsize: The size of the L-vector. This vector may be larger than
162d979a051Sjeremylt                      the elements and fields given by this restriction.
16369a53589Sjeremylt             *strides: Array for strides between [nodes, components, elements].
16469a53589Sjeremylt                         The data for node i, component j, element k in the
16569a53589Sjeremylt                         L-vector is given by
16669a53589Sjeremylt                           i*strides[0] + j*strides[1] + k*strides[2]
16739b2de37Sjeremylt
16839b2de37Sjeremylt           Returns:
16969a53589Sjeremylt             elemrestriction: Ceed Strided ElemRestiction"""
17039b2de37Sjeremylt
1717a7b0fa3SJed Brown        return StridedElemRestriction(
172d979a051Sjeremylt            self, nelem, elemsize, ncomp, lsize, strides)
17339b2de37Sjeremylt
174d979a051Sjeremylt    def BlockedElemRestriction(self, nelem, elemsize, blksize, ncomp, compstride,
175d979a051Sjeremylt                               lsize, offsets, memtype=lib.CEED_MEM_HOST,
176d979a051Sjeremylt                               cmode=lib.CEED_COPY_VALUES):
177d979a051Sjeremylt        """Ceed Blocked ElemRestriction: blocked restriction from local vectors
178d979a051Sjeremylt             to elements.
17939b2de37Sjeremylt
18039b2de37Sjeremylt           Args:
181d979a051Sjeremylt             nelem: number of elements described by the restriction
18239b2de37Sjeremylt             elemsize: size (number of nodes) per element
18339b2de37Sjeremylt             blksize: number of elements in a block
184d979a051Sjeremylt             ncomp: number of field components per interpolation node
185d979a051Sjeremylt                       (1 for scalar fields)
186d979a051Sjeremylt             lsize: The size of the L-vector. This vector may be larger than
187d979a051Sjeremylt                      the elements and fields given by this restriction.
188d979a051Sjeremylt             *offsets: Numpy array of shape [nelem, elemsize]. Row i holds the
189d979a051Sjeremylt                         ordered list of the offsets (into the input Ceed Vector)
19039b2de37Sjeremylt                         for the unknowns corresponding to element i, where
191d979a051Sjeremylt                         0 <= i < nelem. All offsets must be in the range
192d979a051Sjeremylt                         [0, lsize - 1]. The backend will permute and pad this
19339b2de37Sjeremylt                         array to the desired ordering for the blocksize, which is
19439b2de37Sjeremylt                         typically given by the backend. The default reordering is
19539b2de37Sjeremylt                         to interlace elements.
196d979a051Sjeremylt             **memtype: memory type of the offsets array, default CEED_MEM_HOST
197d979a051Sjeremylt             **cmode: copy mode for the offsets array, default CEED_COPY_VALUES
19839b2de37Sjeremylt
19939b2de37Sjeremylt           Returns:
20039b2de37Sjeremylt             elemrestriction: Ceed Blocked ElemRestiction"""
20139b2de37Sjeremylt
202d979a051Sjeremylt        return BlockedElemRestriction(self, nelem, elemsize, blksize, ncomp,
203d979a051Sjeremylt                                      compstride, lsize, offsets,
204d979a051Sjeremylt                                      memtype=memtype, cmode=cmode)
20539b2de37Sjeremylt
206d979a051Sjeremylt    def BlockedStridedElemRestriction(self, nelem, elemsize, blksize, ncomp,
207d979a051Sjeremylt                                      lsize, strides):
208d979a051Sjeremylt        """Ceed Blocked Strided ElemRestriction: blocked and strided restriction
209d979a051Sjeremylt             from local vectors to elements.
21069a53589Sjeremylt
21169a53589Sjeremylt           Args:
212d979a051Sjeremylt             nelem: number of elements described in the restriction
21369a53589Sjeremylt             elemsize: size (number of nodes) per element
21469a53589Sjeremylt             blksize: number of elements in a block
21569a53589Sjeremylt             ncomp: number of field components per interpolation node
21669a53589Sjeremylt                      (1 for scalar fields)
217d979a051Sjeremylt             lsize: The size of the L-vector. This vector may be larger than
218d979a051Sjeremylt                      the elements and fields given by this restriction.
21969a53589Sjeremylt             *strides: Array for strides between [nodes, components, elements].
22069a53589Sjeremylt                         The data for node i, component j, element k in the
22169a53589Sjeremylt                         L-vector is given by
22269a53589Sjeremylt                           i*strides[0] + j*strides[1] + k*strides[2]
22369a53589Sjeremylt
22469a53589Sjeremylt           Returns:
22569a53589Sjeremylt             elemrestriction: Ceed Strided ElemRestiction"""
22669a53589Sjeremylt
22769a53589Sjeremylt        return BlockedStridedElemRestriction(self, nelem, elemsize, blksize,
228d979a051Sjeremylt                                             ncomp, lsize, strides)
22969a53589Sjeremylt
23039b2de37Sjeremylt    # CeedBasis
23139b2de37Sjeremylt    def BasisTensorH1(self, dim, ncomp, P1d, Q1d, interp1d, grad1d,
23239b2de37Sjeremylt                      qref1d, qweight1d):
23339b2de37Sjeremylt        """Ceed Tensor H1 Basis: finite element tensor-product basis objects for
23439b2de37Sjeremylt             H^1 discretizations.
23539b2de37Sjeremylt
23639b2de37Sjeremylt           Args:
23739b2de37Sjeremylt             dim: topological dimension
23839b2de37Sjeremylt             ncomp: number of field components (1 for scalar fields)
23939b2de37Sjeremylt             P1d: number of nodes in one dimension
24039b2de37Sjeremylt             Q1d: number of quadrature points in one dimension
241d979a051Sjeremylt             *interp1d: Numpy array holding the row-major (Q1d * P1d) matrix
242d979a051Sjeremylt                          expressing the values of nodal basis functions at
243d979a051Sjeremylt                          quadrature points
244d979a051Sjeremylt             *grad1d: Numpy array holding the row-major (Q1d * P1d) matrix
245d979a051Sjeremylt                        expressing the derivatives of nodal basis functions at
246d979a051Sjeremylt                        quadrature points
247d979a051Sjeremylt             *qref1d: Numpy array of length Q1d holding the locations of
248d979a051Sjeremylt                        quadrature points on the 1D reference element [-1, 1]
249d979a051Sjeremylt             *qweight1d: Numpy array of length Q1d holding the quadrature
250d979a051Sjeremylt                           weights on the reference element
25139b2de37Sjeremylt
25239b2de37Sjeremylt           Returns:
25339b2de37Sjeremylt             basis: Ceed Basis"""
25439b2de37Sjeremylt
25539b2de37Sjeremylt        return BasisTensorH1(self, dim, ncomp, P1d, Q1d, interp1d, grad1d,
25639b2de37Sjeremylt                             qref1d, qweight1d)
25739b2de37Sjeremylt
25839b2de37Sjeremylt    def BasisTensorH1Lagrange(self, dim, ncomp, P, Q, qmode):
259d979a051Sjeremylt        """Ceed Tensor H1 Lagrange Basis: finite element tensor-product Lagrange
260d979a051Sjeremylt             basis objects for H^1 discretizations.
26139b2de37Sjeremylt
26239b2de37Sjeremylt           Args:
26339b2de37Sjeremylt             dim: topological dimension
26439b2de37Sjeremylt             ncomp: number of field components (1 for scalar fields)
26539b2de37Sjeremylt             P: number of Gauss-Lobatto nodes in one dimension.  The
26639b2de37Sjeremylt                  polynomial degree of the resulting Q_k element is k=P-1.
26739b2de37Sjeremylt             Q: number of quadrature points in one dimension
26839b2de37Sjeremylt             qmode: distribution of the Q quadrature points (affects order of
26939b2de37Sjeremylt                      accuracy for the quadrature)
27039b2de37Sjeremylt
27139b2de37Sjeremylt           Returns:
27239b2de37Sjeremylt             basis: Ceed Basis"""
27339b2de37Sjeremylt
27439b2de37Sjeremylt        return BasisTensorH1Lagrange(self, dim, ncomp, P, Q, qmode)
27539b2de37Sjeremylt
27639b2de37Sjeremylt    def BasisH1(self, topo, ncomp, nnodes, nqpts, interp, grad, qref, qweight):
277d979a051Sjeremylt        """Ceed H1 Basis: finite element non tensor-product basis for H^1
278d979a051Sjeremylt             discretizations.
27939b2de37Sjeremylt
28039b2de37Sjeremylt           Args:
28139b2de37Sjeremylt             topo: topology of the element, e.g. hypercube, simplex, etc
28239b2de37Sjeremylt             ncomp: number of field components (1 for scalar fields)
28339b2de37Sjeremylt             nnodes: total number of nodes
28439b2de37Sjeremylt             nqpts: total number of quadrature points
285d979a051Sjeremylt             *interp: Numpy array holding the row-major (nqpts * nnodes) matrix
286d979a051Sjeremylt                       expressing the values of nodal basis functions at
28739b2de37Sjeremylt                       quadrature points
288d979a051Sjeremylt             *grad: Numpy array holding the row-major (nqpts * dim * nnodes)
289d979a051Sjeremylt                     matrix expressing the derivatives of nodal basis functions
290d979a051Sjeremylt                     at quadrature points
291d979a051Sjeremylt             *qref: Numpy array of length (nqpts * dim) holding the locations of
292d979a051Sjeremylt                     quadrature points on the reference element [-1, 1]
293d979a051Sjeremylt             *qweight: Numpy array of length nnodes holding the quadrature
294d979a051Sjeremylt                        weights on the reference element
29539b2de37Sjeremylt
29639b2de37Sjeremylt           Returns:
29739b2de37Sjeremylt             basis: Ceed Basis"""
29839b2de37Sjeremylt
2997a7b0fa3SJed Brown        return BasisH1(self, topo, ncomp, nnodes, nqpts,
3007a7b0fa3SJed Brown                       interp, grad, qref, qweight)
30139b2de37Sjeremylt
30239b2de37Sjeremylt    # CeedQFunction
30339b2de37Sjeremylt    def QFunction(self, vlength, f, source):
304d979a051Sjeremylt        """Ceed QFunction: point-wise operation at quadrature points for
305d979a051Sjeremylt             evaluating volumetric terms.
30639b2de37Sjeremylt
30739b2de37Sjeremylt           Args:
30839b2de37Sjeremylt             vlength: vector length. Caller must ensure that number of quadrature
30939b2de37Sjeremylt                        points is a multiple of vlength
31039b2de37Sjeremylt             f: ctypes function pointer to evaluate action at quadrature points
31139b2de37Sjeremylt             source: absolute path to source of QFunction,
31239b2de37Sjeremylt               "\\abs_path\\file.h:function_name
31339b2de37Sjeremylt
31439b2de37Sjeremylt           Returns:
31539b2de37Sjeremylt             qfunction: Ceed QFunction"""
31639b2de37Sjeremylt
31739b2de37Sjeremylt        return QFunction(self, vlength, f, source)
31839b2de37Sjeremylt
31939b2de37Sjeremylt    def QFunctionByName(self, name):
32039b2de37Sjeremylt        """Ceed QFunction By Name: point-wise operation at quadrature points
32139b2de37Sjeremylt             from a given gallery, for evaluating volumetric terms.
32239b2de37Sjeremylt
32339b2de37Sjeremylt           Args:
32439b2de37Sjeremylt             name: name of QFunction to use from gallery
32539b2de37Sjeremylt
32639b2de37Sjeremylt           Returns:
32739b2de37Sjeremylt             qfunction: Ceed QFunction By Name"""
32839b2de37Sjeremylt
32939b2de37Sjeremylt        return QFunctionByName(self, name)
33039b2de37Sjeremylt
33139b2de37Sjeremylt    def IdentityQFunction(self, size, inmode, outmode):
33239b2de37Sjeremylt        """Ceed Idenity QFunction: identity qfunction operation.
33339b2de37Sjeremylt
33439b2de37Sjeremylt           Args:
33539b2de37Sjeremylt             size: size of the qfunction fields
33639b2de37Sjeremylt             **inmode: CeedEvalMode for input to Ceed QFunction
33739b2de37Sjeremylt             **outmode: CeedEvalMode for output to Ceed QFunction
33839b2de37Sjeremylt
33939b2de37Sjeremylt           Returns:
34039b2de37Sjeremylt             qfunction: Ceed Identity QFunction"""
34139b2de37Sjeremylt
34239b2de37Sjeremylt        return IdentityQFunction(self, size, inmode, outmode)
34339b2de37Sjeremylt
344*777ff853SJeremy L Thompson    def QFunctionContext(self):
345*777ff853SJeremy L Thompson        """Ceed QFunction Context: stores Ceed QFunction user context data.
346*777ff853SJeremy L Thompson
347*777ff853SJeremy L Thompson           Returns:
348*777ff853SJeremy L Thompson             userContext: Ceed QFunction Context"""
349*777ff853SJeremy L Thompson
350*777ff853SJeremy L Thompson        return QFunctionContext(self)
351*777ff853SJeremy L Thompson
35239b2de37Sjeremylt    # CeedOperator
35339b2de37Sjeremylt    def Operator(self, qf, dqf=None, qdfT=None):
35439b2de37Sjeremylt        """Ceed Operator: composed FE-type operations on vectors.
35539b2de37Sjeremylt
35639b2de37Sjeremylt           Args:
357d979a051Sjeremylt             qf: QFunction defining the action of the operator at quadrature
358d979a051Sjeremylt                   points
35939b2de37Sjeremylt             **dqf: QFunction defining the action of the Jacobian, default None
360d979a051Sjeremylt             **dqfT: QFunction defining the action of the transpose of the
361d979a051Sjeremylt                       Jacobian, default None
36239b2de37Sjeremylt
36339b2de37Sjeremylt           Returns:
36439b2de37Sjeremylt             operator: Ceed Operator"""
36539b2de37Sjeremylt
36639b2de37Sjeremylt        return Operator(self, qf, dqf, qdfT)
36739b2de37Sjeremylt
36839b2de37Sjeremylt    def CompositeOperator(self):
36939b2de37Sjeremylt        """Composite Ceed Operator: composition of multiple CeedOperators.
37039b2de37Sjeremylt
37139b2de37Sjeremylt           Returns:
37239b2de37Sjeremylt             operator: Ceed Composite Operator"""
37339b2de37Sjeremylt
37439b2de37Sjeremylt        return CompositeOperator(self)
37539b2de37Sjeremylt
37639b2de37Sjeremylt    # Destructor
37739b2de37Sjeremylt    def __del__(self):
37839b2de37Sjeremylt        # libCEED call
37939b2de37Sjeremylt        lib.CeedDestroy(self._pointer)
38039b2de37Sjeremylt
38139b2de37Sjeremylt# ------------------------------------------------------------------------------
382