xref: /libCEED/python/ceed_operator.py (revision 28d09c206720ba8516c835daf824672e3380cdbd)
1f2d2bf5dSjeremylt# Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2f2d2bf5dSjeremylt# the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3f2d2bf5dSjeremylt# reserved. See files LICENSE and NOTICE for details.
4f2d2bf5dSjeremylt#
5f2d2bf5dSjeremylt# This file is part of CEED, a collection of benchmarks, miniapps, software
6f2d2bf5dSjeremylt# libraries and APIs for efficient high-order finite element and spectral
7f2d2bf5dSjeremylt# element discretizations for exascale applications. For more information and
8f2d2bf5dSjeremylt# source code availability see http://github.com/ceed.
9f2d2bf5dSjeremylt#
10f2d2bf5dSjeremylt# The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11f2d2bf5dSjeremylt# a collaborative effort of two U.S. Department of Energy organizations (Office
12f2d2bf5dSjeremylt# of Science and the National Nuclear Security Administration) responsible for
13f2d2bf5dSjeremylt# the planning and preparation of a capable exascale ecosystem, including
14f2d2bf5dSjeremylt# software, applications, hardware, advanced system engineering and early
15f2d2bf5dSjeremylt# testbed platforms, in support of the nation's exascale computing imperative.
16f2d2bf5dSjeremylt
17f2d2bf5dSjeremyltfrom _ceed_cffi import ffi, lib
18f2d2bf5dSjeremyltimport tempfile
19f2d2bf5dSjeremyltfrom abc import ABC
20f2d2bf5dSjeremyltfrom .ceed_constants import REQUEST_IMMEDIATE, REQUEST_ORDERED, NOTRANSPOSE
21f2d2bf5dSjeremylt
22f2d2bf5dSjeremylt# ------------------------------------------------------------------------------
237a7b0fa3SJed Brown
247a7b0fa3SJed Brown
25f2d2bf5dSjeremyltclass _OperatorBase(ABC):
26f2d2bf5dSjeremylt    """Ceed Operator: composed FE-type operations on vectors."""
27f2d2bf5dSjeremylt
28f2d2bf5dSjeremylt    # Destructor
29f2d2bf5dSjeremylt    def __del__(self):
30f2d2bf5dSjeremylt        # libCEED call
31477729cfSJeremy L Thompson        err_code = lib.CeedOperatorDestroy(self._pointer)
32477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
33f2d2bf5dSjeremylt
34f2d2bf5dSjeremylt    # Representation
35f2d2bf5dSjeremylt    def __repr__(self):
36f2d2bf5dSjeremylt        return "<CeedOperator instance at " + hex(id(self)) + ">"
37f2d2bf5dSjeremylt
38f2d2bf5dSjeremylt    # String conversion for print() to stdout
39f2d2bf5dSjeremylt    def __str__(self):
40f2d2bf5dSjeremylt        """View an Operator via print()."""
41f2d2bf5dSjeremylt
42f2d2bf5dSjeremylt        # libCEED call
43f2d2bf5dSjeremylt        with tempfile.NamedTemporaryFile() as key_file:
44f2d2bf5dSjeremylt            with open(key_file.name, 'r+') as stream_file:
45f2d2bf5dSjeremylt                stream = ffi.cast("FILE *", stream_file)
46f2d2bf5dSjeremylt
47477729cfSJeremy L Thompson                err_code = lib.CeedOperatorView(self._pointer[0], stream)
48477729cfSJeremy L Thompson                self._ceed._check_error(err_code)
49f2d2bf5dSjeremylt
50f2d2bf5dSjeremylt                stream_file.seek(0)
51f2d2bf5dSjeremylt                out_string = stream_file.read()
52f2d2bf5dSjeremylt
53f2d2bf5dSjeremylt        return out_string
54f2d2bf5dSjeremylt
55*28d09c20SJeremy L Thompson    # Check Operator setup
56*28d09c20SJeremy L Thompson    def check(self):
57*28d09c20SJeremy L Thompson        """Check if a CeedOperator is ready to be used"""
58*28d09c20SJeremy L Thompson        # libCEED call
59*28d09c20SJeremy L Thompson        err_code = lib.CeedOperatorCheckReady(self._pointer[0])
60*28d09c20SJeremy L Thompson        self._ceed._check_error(err_code)
61*28d09c20SJeremy L Thompson
626397b31bSJeremy L Thompson    # Assemble linear diagonal
636397b31bSJeremy L Thompson    def linear_assemble_diagonal(self, d, request=REQUEST_IMMEDIATE):
646397b31bSJeremy L Thompson        """Assemble the diagonal of a square linear Operator
656397b31bSJeremy L Thompson
666397b31bSJeremy L Thompson           Args:
676397b31bSJeremy L Thompson             d: Vector to store assembled Operator diagonal
686397b31bSJeremy L Thompson             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
696397b31bSJeremy L Thompson
706397b31bSJeremy L Thompson        # libCEED call
71477729cfSJeremy L Thompson        err_code = lib.CeedOperatorLinearAssembleDiagonal(self._pointer[0],
726397b31bSJeremy L Thompson                                                          d._pointer[0], request)
73477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
746397b31bSJeremy L Thompson
756397b31bSJeremy L Thompson    # Assemble add linear diagonal
766397b31bSJeremy L Thompson    def linear_assemble_add_diagonal(self, d, request=REQUEST_IMMEDIATE):
776397b31bSJeremy L Thompson        """Sum the diagonal of a square linear Operator into a Vector
786397b31bSJeremy L Thompson
796397b31bSJeremy L Thompson           Args:
806397b31bSJeremy L Thompson             d: Vector to store assembled Operator diagonal
816397b31bSJeremy L Thompson             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
826397b31bSJeremy L Thompson
836397b31bSJeremy L Thompson        # libCEED call
84477729cfSJeremy L Thompson        err_code = lib.CeedOperatorLinearAssembleAddDiagonal(self._pointer[0],
856397b31bSJeremy L Thompson                                                             d._pointer[0], request)
86477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
876397b31bSJeremy L Thompson
886397b31bSJeremy L Thompson    # Assemble linear point block diagonal
890c9255dfSJeremy L Thompson    def linear_assemble_point_block_diagonal(
900c9255dfSJeremy L Thompson            self, d, request=REQUEST_IMMEDIATE):
910c9255dfSJeremy L Thompson        """Assemble the point block diagonal of a square linear Operator
926397b31bSJeremy L Thompson
936397b31bSJeremy L Thompson           Args:
946397b31bSJeremy L Thompson             d: Vector to store assembled Operator point block diagonal,
956397b31bSJeremy L Thompson                  provided in row-major form with an ncomp*ncomp block
966397b31bSJeremy L Thompson                  at each node
976397b31bSJeremy L Thompson             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
986397b31bSJeremy L Thompson
996397b31bSJeremy L Thompson        # libCEED call
100477729cfSJeremy L Thompson        err_code = lib.CeedOperatorLinearAssemblePointBlockDiagonal(self._pointer[0],
1016397b31bSJeremy L Thompson                                                                    d._pointer[0], request)
102477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
1036397b31bSJeremy L Thompson
1046397b31bSJeremy L Thompson    # Assemble linear point block diagonal
1050c9255dfSJeremy L Thompson    def linear_assemble_add_point_block_diagonal(
1060c9255dfSJeremy L Thompson            self, d, request=REQUEST_IMMEDIATE):
1070c9255dfSJeremy L Thompson        """Sum the point block diagonal of a square linear Operator into a Vector
1086397b31bSJeremy L Thompson
1096397b31bSJeremy L Thompson           Args:
1106397b31bSJeremy L Thompson             d: Vector to store assembled Operator point block diagonal,
1116397b31bSJeremy L Thompson                  provided in row-major form with an ncomp*ncomp block
1126397b31bSJeremy L Thompson                  at each node
1136397b31bSJeremy L Thompson             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
1146397b31bSJeremy L Thompson
1156397b31bSJeremy L Thompson        # libCEED call
116477729cfSJeremy L Thompson        err_code = lib.CeedOperatorLinearAssembleAddPointBlockDiagonal(self._pointer[0],
1176397b31bSJeremy L Thompson                                                                       d._pointer[0], request)
118477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
1196397b31bSJeremy L Thompson
120f2d2bf5dSjeremylt    # Apply CeedOperator
121f2d2bf5dSjeremylt    def apply(self, u, v, request=REQUEST_IMMEDIATE):
122f2d2bf5dSjeremylt        """Apply Operator to a vector.
123f2d2bf5dSjeremylt
124f2d2bf5dSjeremylt           Args:
125f2d2bf5dSjeremylt             u: Vector containing input state or CEED_VECTOR_NONE if there are no
126f2d2bf5dSjeremylt                  active inputs
127f2d2bf5dSjeremylt             v: Vector to store result of applying operator (must be distinct from u)
128f2d2bf5dSjeremylt                  or CEED_VECTOR_NONE if there are no active outputs
129f2d2bf5dSjeremylt             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
130f2d2bf5dSjeremylt
131f2d2bf5dSjeremylt        # libCEED call
132477729cfSJeremy L Thompson        err_code = lib.CeedOperatorApply(self._pointer[0], u._pointer[0], v._pointer[0],
133f2d2bf5dSjeremylt                                         request)
134477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
135f2d2bf5dSjeremylt
136f2d2bf5dSjeremylt    # Apply CeedOperator
137f2d2bf5dSjeremylt    def apply_add(self, u, v, request=REQUEST_IMMEDIATE):
138f2d2bf5dSjeremylt        """Apply Operator to a vector and add result to output vector.
139f2d2bf5dSjeremylt
140f2d2bf5dSjeremylt           Args:
141f2d2bf5dSjeremylt             u: Vector containing input state or CEED_VECTOR_NONE if there are no
142f2d2bf5dSjeremylt                  active inputs
143f2d2bf5dSjeremylt             v: Vector to sum in result of applying operator (must be distinct from u)
144f2d2bf5dSjeremylt                  or CEED_VECTOR_NONE if there are no active outputs
145f2d2bf5dSjeremylt             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
146f2d2bf5dSjeremylt
147f2d2bf5dSjeremylt        # libCEED call
148477729cfSJeremy L Thompson        err_code = lib.CeedOperatorApplyAdd(self._pointer[0], u._pointer[0], v._pointer[0],
149f2d2bf5dSjeremylt                                            request)
150477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
151f2d2bf5dSjeremylt
152d99fa3c5SJeremy L Thompson    # Create Multigrid Level
153d99fa3c5SJeremy L Thompson    def multigrid_create(self, p_mult_fine, rstr_coarse, basis_coarse):
154d99fa3c5SJeremy L Thompson        """ Create a multigrid coarse operator and level transfer operators
155d99fa3c5SJeremy L Thompson           for a CeedOperator with a Lagrange tensor basis for the active basis
156d99fa3c5SJeremy L Thompson
157d99fa3c5SJeremy L Thompson           Args:
158d99fa3c5SJeremy L Thompson             p_mult_fine: L-vector multiplicity in parallel gather/scatter
159d99fa3c5SJeremy L Thompson             basis_coarse: Coarse grid active vector basis
160d99fa3c5SJeremy L Thompson             degree_coarse: Coarse grid basis polynomial order"""
161d99fa3c5SJeremy L Thompson
162d99fa3c5SJeremy L Thompson        # Operator pointers
163d99fa3c5SJeremy L Thompson        opCoarsePointer = ffi.new("CeedOperator *")
164d99fa3c5SJeremy L Thompson        opProlongPointer = ffi.new("CeedOperator *")
165d99fa3c5SJeremy L Thompson        opRestrictPointer = ffi.new("CeedOperator *")
166d99fa3c5SJeremy L Thompson
167d99fa3c5SJeremy L Thompson        # libCEED call
168d99fa3c5SJeremy L Thompson        lib.CeedOperatorMultigridLevelCreate(self._pointer[0],
169d99fa3c5SJeremy L Thompson                                             p_mult_fine._pointer[0],
170d99fa3c5SJeremy L Thompson                                             rstr_coarse._pointer[0],
171d99fa3c5SJeremy L Thompson                                             basis_coarse._pointer[0],
172d99fa3c5SJeremy L Thompson                                             opCoarsePointer,
173d99fa3c5SJeremy L Thompson                                             opProlongPointer,
174d99fa3c5SJeremy L Thompson                                             opRestrictPointer)
175d99fa3c5SJeremy L Thompson
176d99fa3c5SJeremy L Thompson        # Wrap operators
177d99fa3c5SJeremy L Thompson        opCoarse = _OperatorWrap(
178d99fa3c5SJeremy L Thompson            self._ceed, opCoarsePointer)
179d99fa3c5SJeremy L Thompson        opProlong = _OperatorWrap(
180d99fa3c5SJeremy L Thompson            self._ceed, opProlongPointer)
181d99fa3c5SJeremy L Thompson        opRestrict = _OperatorWrap(
182d99fa3c5SJeremy L Thompson            self._ceed, opRestrictPointer)
183d99fa3c5SJeremy L Thompson
184d99fa3c5SJeremy L Thompson        # Return
185d99fa3c5SJeremy L Thompson        return [opCoarse, opProlong, opRestrict]
186d99fa3c5SJeremy L Thompson
187d99fa3c5SJeremy L Thompson    # Create Multigrid Level
188d99fa3c5SJeremy L Thompson    def multigrid_create_tensor_h1(self, p_mult_fine, rstr_coarse, basis_coarse,
189d99fa3c5SJeremy L Thompson                                   interp_C_to_F):
190d99fa3c5SJeremy L Thompson        """ Create a multigrid coarse operator and level transfer operators
191d99fa3c5SJeremy L Thompson           for a CeedOperator with a non-tensor basis for the active basis
192d99fa3c5SJeremy L Thompson
193d99fa3c5SJeremy L Thompson           Args:
194d99fa3c5SJeremy L Thompson             p_mult_fine: L-vector multiplicity in parallel gather/scatter
195d99fa3c5SJeremy L Thompson             rstr_coarse: Coarse grid restriction
196d99fa3c5SJeremy L Thompson             basis_coarse: Coarse grid active vector basis
197d99fa3c5SJeremy L Thompson             interp_C_to_F: Matrix for coarse to fine interpolation"""
198d99fa3c5SJeremy L Thompson
199d99fa3c5SJeremy L Thompson       # Setup arguments
200d99fa3c5SJeremy L Thompson        interpCtoF_pointer = ffi.new("CeedScalar *")
201d99fa3c5SJeremy L Thompson        interpCtoF_pointer = ffi.cast(
202d99fa3c5SJeremy L Thompson            "CeedScalar *",
203d99fa3c5SJeremy L Thompson            interp_C_to_F.__array_interface__['data'][0])
204d99fa3c5SJeremy L Thompson
205d99fa3c5SJeremy L Thompson        # Operator pointers
206d99fa3c5SJeremy L Thompson        opCoarsePointer = ffi.new("CeedOperator *")
207d99fa3c5SJeremy L Thompson        opProlongPointer = ffi.new("CeedOperator *")
208d99fa3c5SJeremy L Thompson        opRestrictPointer = ffi.new("CeedOperator *")
209d99fa3c5SJeremy L Thompson
210d99fa3c5SJeremy L Thompson        # libCEED call
211d99fa3c5SJeremy L Thompson        lib.CeedOperatorMultigridLevelCreateTensorH1(self._pointer[0],
212d99fa3c5SJeremy L Thompson                                                     p_mult_fine._pointer[0],
213d99fa3c5SJeremy L Thompson                                                     rstr_coarse._pointer[0],
214d99fa3c5SJeremy L Thompson                                                     basis_coarse._pointer[0],
215d99fa3c5SJeremy L Thompson                                                     interpCtoF_pointer,
216d99fa3c5SJeremy L Thompson                                                     opCoarsePointer,
217d99fa3c5SJeremy L Thompson                                                     opProlongPointer,
218d99fa3c5SJeremy L Thompson                                                     opRestrictPointer)
219d99fa3c5SJeremy L Thompson
220d99fa3c5SJeremy L Thompson        # Wrap operators
221d99fa3c5SJeremy L Thompson        opCoarse = _OperatorWrap(
222d99fa3c5SJeremy L Thompson            self._ceed, opCoarsePointer)
223d99fa3c5SJeremy L Thompson        opProlong = _OperatorWrap(
224d99fa3c5SJeremy L Thompson            self._ceed, opProlongPointer)
225d99fa3c5SJeremy L Thompson        opRestrict = _OperatorWrap(
226d99fa3c5SJeremy L Thompson            self._ceed, opRestrictPointer)
227d99fa3c5SJeremy L Thompson
228d99fa3c5SJeremy L Thompson        # Return
229d99fa3c5SJeremy L Thompson        return [opCoarse, opProlong, opRestrict]
230d99fa3c5SJeremy L Thompson
231d99fa3c5SJeremy L Thompson    # Create Multigrid Level
232d99fa3c5SJeremy L Thompson    def multigrid_create_h1(self, p_mult_fine, rstr_coarse, basis_coarse,
233d99fa3c5SJeremy L Thompson                            interp_C_to_F):
234d99fa3c5SJeremy L Thompson        """ Create a multigrid coarse operator and level transfer operators
235d99fa3c5SJeremy L Thompson           for a CeedOperator with a Lagrange tensor basis for the active basis
236d99fa3c5SJeremy L Thompson
237d99fa3c5SJeremy L Thompson           Args:
238d99fa3c5SJeremy L Thompson             p_mult_fine: L-vector multiplicity in parallel gather/scatter
239d99fa3c5SJeremy L Thompson             rstr_coarse: Coarse grid restriction
240d99fa3c5SJeremy L Thompson             basis_coarse: Coarse grid active vector basis
241d99fa3c5SJeremy L Thompson             interp_C_to_F: Matrix for coarse to fine interpolation"""
242d99fa3c5SJeremy L Thompson
243d99fa3c5SJeremy L Thompson       # Setup arguments
244d99fa3c5SJeremy L Thompson        interpCtoF_pointer = ffi.new("CeedScalar *")
245d99fa3c5SJeremy L Thompson        interpCtoF_pointer = ffi.cast(
246d99fa3c5SJeremy L Thompson            "CeedScalar *",
247d99fa3c5SJeremy L Thompson            interp_C_to_F.__array_interface__['data'][0])
248d99fa3c5SJeremy L Thompson
249d99fa3c5SJeremy L Thompson        # Operator pointers
250d99fa3c5SJeremy L Thompson        opCoarsePointer = ffi.new("CeedOperator *")
251d99fa3c5SJeremy L Thompson        opProlongPointer = ffi.new("CeedOperator *")
252d99fa3c5SJeremy L Thompson        opRestrictPointer = ffi.new("CeedOperator *")
253d99fa3c5SJeremy L Thompson
254d99fa3c5SJeremy L Thompson        # libCEED call
255d99fa3c5SJeremy L Thompson        lib.CeedOperatorMultigridLevelCreateH1(self._pointer[0],
256d99fa3c5SJeremy L Thompson                                               p_mult_fine._pointer[0],
257d99fa3c5SJeremy L Thompson                                               rstr_coarse._pointer[0],
258d99fa3c5SJeremy L Thompson                                               basis_coarse._pointer[0],
259d99fa3c5SJeremy L Thompson                                               interpCtoF_pointer,
260d99fa3c5SJeremy L Thompson                                               opCoarsePointer,
261d99fa3c5SJeremy L Thompson                                               opProlongPointer,
262d99fa3c5SJeremy L Thompson                                               opRestrictPointer)
263d99fa3c5SJeremy L Thompson
264d99fa3c5SJeremy L Thompson        # Wrap operators
265d99fa3c5SJeremy L Thompson        opCoarse = _OperatorWrap(
266d99fa3c5SJeremy L Thompson            self._ceed, opCoarsePointer)
267d99fa3c5SJeremy L Thompson        opProlong = _OperatorWrap(
268d99fa3c5SJeremy L Thompson            self._ceed, opProlongPointer)
269d99fa3c5SJeremy L Thompson        opRestrict = _OperatorWrap(
270d99fa3c5SJeremy L Thompson            self._ceed, opRestrictPointer)
271d99fa3c5SJeremy L Thompson
272d99fa3c5SJeremy L Thompson        # Return
273d99fa3c5SJeremy L Thompson        return [opCoarse, opProlong, opRestrict]
274d99fa3c5SJeremy L Thompson
275d99fa3c5SJeremy L Thompson
276f2d2bf5dSjeremylt# ------------------------------------------------------------------------------
2777a7b0fa3SJed Brown
2787a7b0fa3SJed Brown
279f2d2bf5dSjeremyltclass Operator(_OperatorBase):
280f2d2bf5dSjeremylt    """Ceed Operator: composed FE-type operations on vectors."""
281f2d2bf5dSjeremylt
282f2d2bf5dSjeremylt    # Constructor
283f2d2bf5dSjeremylt    def __init__(self, ceed, qf, dqf=None, dqfT=None):
284f2d2bf5dSjeremylt        # CeedOperator object
285f2d2bf5dSjeremylt        self._pointer = ffi.new("CeedOperator *")
286f2d2bf5dSjeremylt
287f2d2bf5dSjeremylt        # Reference to Ceed
288f2d2bf5dSjeremylt        self._ceed = ceed
289f2d2bf5dSjeremylt
290f2d2bf5dSjeremylt        # libCEED call
291477729cfSJeremy L Thompson        err_code = lib.CeedOperatorCreate(self._ceed._pointer[0], qf._pointer[0],
292f2d2bf5dSjeremylt                                          dqf._pointer[0] if dqf else ffi.NULL,
293f2d2bf5dSjeremylt                                          dqfT._pointer[0] if dqfT else ffi.NULL,
294f2d2bf5dSjeremylt                                          self._pointer)
295477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
296f2d2bf5dSjeremylt
297f2d2bf5dSjeremylt    # Add field to CeedOperator
298a8d32208Sjeremylt    def set_field(self, fieldname, restriction, basis, vector):
299f2d2bf5dSjeremylt        """Provide a field to an Operator for use by its QFunction.
300f2d2bf5dSjeremylt
301f2d2bf5dSjeremylt           Args:
302f2d2bf5dSjeremylt             fieldname: name of the field (to be matched with the same name used
303f2d2bf5dSjeremylt                          by QFunction)
304f2d2bf5dSjeremylt             restriction: ElemRestriction
305f2d2bf5dSjeremylt             basis: Basis in which the field resides or CEED_BASIS_COLLOCATED
306f2d2bf5dSjeremylt                      if collocated with quadrature points
307f2d2bf5dSjeremylt             vector: Vector to be used by Operator or CEED_VECTOR_ACTIVE
308f2d2bf5dSjeremylt                       if field is active or CEED_VECTOR_NONE if using
309a8d32208Sjeremylt                       CEED_EVAL_WEIGHT in the QFunction"""
310f2d2bf5dSjeremylt
311f2d2bf5dSjeremylt        # libCEED call
312f2d2bf5dSjeremylt        fieldnameAscii = ffi.new("char[]", fieldname.encode('ascii'))
313477729cfSJeremy L Thompson        err_code = lib.CeedOperatorSetField(self._pointer[0], fieldnameAscii,
314a8d32208Sjeremylt                                            restriction._pointer[0], basis._pointer[0],
315f2d2bf5dSjeremylt                                            vector._pointer[0])
316477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
317f2d2bf5dSjeremylt
318f2d2bf5dSjeremylt# ------------------------------------------------------------------------------
3197a7b0fa3SJed Brown
3207a7b0fa3SJed Brown
321f2d2bf5dSjeremyltclass CompositeOperator(_OperatorBase):
322f2d2bf5dSjeremylt    """Ceed Composite Operator: composition of multiple Operators."""
323f2d2bf5dSjeremylt
324f2d2bf5dSjeremylt    # Constructor
325f2d2bf5dSjeremylt    def __init__(self, ceed):
326f2d2bf5dSjeremylt        # CeedOperator object
327f2d2bf5dSjeremylt        self._pointer = ffi.new("CeedOperator *")
328f2d2bf5dSjeremylt
329f2d2bf5dSjeremylt        # Reference to Ceed
330f2d2bf5dSjeremylt        self._ceed = ceed
331f2d2bf5dSjeremylt        # libCEED call
332477729cfSJeremy L Thompson        err_code = lib.CeedCompositeOperatorCreate(
333477729cfSJeremy L Thompson            self._ceed._pointer[0], self._pointer)
334477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
335f2d2bf5dSjeremylt
336f2d2bf5dSjeremylt    # Add sub operators
337f2d2bf5dSjeremylt    def add_sub(self, subop):
338f2d2bf5dSjeremylt        """Add a sub-operator to a composite CeedOperator.
339f2d2bf5dSjeremylt
340f2d2bf5dSjeremylt           Args:
341f2d2bf5dSjeremylt             subop: sub-operator Operator"""
342f2d2bf5dSjeremylt
343f2d2bf5dSjeremylt        # libCEED call
344477729cfSJeremy L Thompson        err_code = lib.CeedCompositeOperatorAddSub(
345477729cfSJeremy L Thompson            self._pointer[0], subop._pointer[0])
346477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
347f2d2bf5dSjeremylt
348f2d2bf5dSjeremylt# ------------------------------------------------------------------------------
349d99fa3c5SJeremy L Thompson
350d99fa3c5SJeremy L Thompson
351d99fa3c5SJeremy L Thompsonclass _OperatorWrap(Operator):
352d99fa3c5SJeremy L Thompson    """Wrap a CeedOperator pointer in a Operator object."""
353d99fa3c5SJeremy L Thompson
354d99fa3c5SJeremy L Thompson    # Constructor
355d99fa3c5SJeremy L Thompson    def __init__(self, ceed, pointer):
356d99fa3c5SJeremy L Thompson        # CeedOperator object
357d99fa3c5SJeremy L Thompson        self._pointer = pointer
358d99fa3c5SJeremy L Thompson
359d99fa3c5SJeremy L Thompson        # Reference to Ceed
360d99fa3c5SJeremy L Thompson        self._ceed = ceed
361d99fa3c5SJeremy L Thompson
362d99fa3c5SJeremy L Thompson# ------------------------------------------------------------------------------
363