xref: /libCEED/python/ceed_operator.py (revision d99fa3c5cd91a1690aedf0679cbf290d44fec74c)
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    # Attributes
29f2d2bf5dSjeremylt    _ceed = ffi.NULL
30f2d2bf5dSjeremylt    _pointer = ffi.NULL
31f2d2bf5dSjeremylt
32f2d2bf5dSjeremylt    # Destructor
33f2d2bf5dSjeremylt    def __del__(self):
34f2d2bf5dSjeremylt        # libCEED call
35477729cfSJeremy L Thompson        err_code = lib.CeedOperatorDestroy(self._pointer)
36477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
37f2d2bf5dSjeremylt
38f2d2bf5dSjeremylt    # Representation
39f2d2bf5dSjeremylt    def __repr__(self):
40f2d2bf5dSjeremylt        return "<CeedOperator instance at " + hex(id(self)) + ">"
41f2d2bf5dSjeremylt
42f2d2bf5dSjeremylt    # String conversion for print() to stdout
43f2d2bf5dSjeremylt    def __str__(self):
44f2d2bf5dSjeremylt        """View an Operator via print()."""
45f2d2bf5dSjeremylt
46f2d2bf5dSjeremylt        # libCEED call
47f2d2bf5dSjeremylt        with tempfile.NamedTemporaryFile() as key_file:
48f2d2bf5dSjeremylt            with open(key_file.name, 'r+') as stream_file:
49f2d2bf5dSjeremylt                stream = ffi.cast("FILE *", stream_file)
50f2d2bf5dSjeremylt
51477729cfSJeremy L Thompson                err_code = lib.CeedOperatorView(self._pointer[0], stream)
52477729cfSJeremy L Thompson                self._ceed._check_error(err_code)
53f2d2bf5dSjeremylt
54f2d2bf5dSjeremylt                stream_file.seek(0)
55f2d2bf5dSjeremylt                out_string = stream_file.read()
56f2d2bf5dSjeremylt
57f2d2bf5dSjeremylt        return out_string
58f2d2bf5dSjeremylt
596397b31bSJeremy L Thompson    # Assemble linear diagonal
606397b31bSJeremy L Thompson    def linear_assemble_diagonal(self, d, request=REQUEST_IMMEDIATE):
616397b31bSJeremy L Thompson        """Assemble the diagonal of a square linear Operator
626397b31bSJeremy L Thompson
636397b31bSJeremy L Thompson           Args:
646397b31bSJeremy L Thompson             d: Vector to store assembled Operator diagonal
656397b31bSJeremy L Thompson             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
666397b31bSJeremy L Thompson
676397b31bSJeremy L Thompson        # libCEED call
68477729cfSJeremy L Thompson        err_code = lib.CeedOperatorLinearAssembleDiagonal(self._pointer[0],
696397b31bSJeremy L Thompson                                                          d._pointer[0], request)
70477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
716397b31bSJeremy L Thompson
726397b31bSJeremy L Thompson    # Assemble add linear diagonal
736397b31bSJeremy L Thompson    def linear_assemble_add_diagonal(self, d, request=REQUEST_IMMEDIATE):
746397b31bSJeremy L Thompson        """Sum the diagonal of a square linear Operator into a Vector
756397b31bSJeremy L Thompson
766397b31bSJeremy L Thompson           Args:
776397b31bSJeremy L Thompson             d: Vector to store assembled Operator diagonal
786397b31bSJeremy L Thompson             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
796397b31bSJeremy L Thompson
806397b31bSJeremy L Thompson        # libCEED call
81477729cfSJeremy L Thompson        err_code = lib.CeedOperatorLinearAssembleAddDiagonal(self._pointer[0],
826397b31bSJeremy L Thompson                                                             d._pointer[0], request)
83477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
846397b31bSJeremy L Thompson
856397b31bSJeremy L Thompson    # Assemble linear point block diagonal
860c9255dfSJeremy L Thompson    def linear_assemble_point_block_diagonal(
870c9255dfSJeremy L Thompson            self, d, request=REQUEST_IMMEDIATE):
880c9255dfSJeremy L Thompson        """Assemble the point block diagonal of a square linear Operator
896397b31bSJeremy L Thompson
906397b31bSJeremy L Thompson           Args:
916397b31bSJeremy L Thompson             d: Vector to store assembled Operator point block diagonal,
926397b31bSJeremy L Thompson                  provided in row-major form with an ncomp*ncomp block
936397b31bSJeremy L Thompson                  at each node
946397b31bSJeremy L Thompson             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
956397b31bSJeremy L Thompson
966397b31bSJeremy L Thompson        # libCEED call
97477729cfSJeremy L Thompson        err_code = lib.CeedOperatorLinearAssemblePointBlockDiagonal(self._pointer[0],
986397b31bSJeremy L Thompson                                                                    d._pointer[0], request)
99477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
1006397b31bSJeremy L Thompson
1016397b31bSJeremy L Thompson    # Assemble linear point block diagonal
1020c9255dfSJeremy L Thompson    def linear_assemble_add_point_block_diagonal(
1030c9255dfSJeremy L Thompson            self, d, request=REQUEST_IMMEDIATE):
1040c9255dfSJeremy L Thompson        """Sum the point block diagonal of a square linear Operator into a Vector
1056397b31bSJeremy L Thompson
1066397b31bSJeremy L Thompson           Args:
1076397b31bSJeremy L Thompson             d: Vector to store assembled Operator point block diagonal,
1086397b31bSJeremy L Thompson                  provided in row-major form with an ncomp*ncomp block
1096397b31bSJeremy L Thompson                  at each node
1106397b31bSJeremy L Thompson             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
1116397b31bSJeremy L Thompson
1126397b31bSJeremy L Thompson        # libCEED call
113477729cfSJeremy L Thompson        err_code = lib.CeedOperatorLinearAssembleAddPointBlockDiagonal(self._pointer[0],
1146397b31bSJeremy L Thompson                                                                       d._pointer[0], request)
115477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
1166397b31bSJeremy L Thompson
117f2d2bf5dSjeremylt    # Apply CeedOperator
118f2d2bf5dSjeremylt    def apply(self, u, v, request=REQUEST_IMMEDIATE):
119f2d2bf5dSjeremylt        """Apply Operator to a vector.
120f2d2bf5dSjeremylt
121f2d2bf5dSjeremylt           Args:
122f2d2bf5dSjeremylt             u: Vector containing input state or CEED_VECTOR_NONE if there are no
123f2d2bf5dSjeremylt                  active inputs
124f2d2bf5dSjeremylt             v: Vector to store result of applying operator (must be distinct from u)
125f2d2bf5dSjeremylt                  or CEED_VECTOR_NONE if there are no active outputs
126f2d2bf5dSjeremylt             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
127f2d2bf5dSjeremylt
128f2d2bf5dSjeremylt        # libCEED call
129477729cfSJeremy L Thompson        err_code = lib.CeedOperatorApply(self._pointer[0], u._pointer[0], v._pointer[0],
130f2d2bf5dSjeremylt                                         request)
131477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
132f2d2bf5dSjeremylt
133f2d2bf5dSjeremylt    # Apply CeedOperator
134f2d2bf5dSjeremylt    def apply_add(self, u, v, request=REQUEST_IMMEDIATE):
135f2d2bf5dSjeremylt        """Apply Operator to a vector and add result to output vector.
136f2d2bf5dSjeremylt
137f2d2bf5dSjeremylt           Args:
138f2d2bf5dSjeremylt             u: Vector containing input state or CEED_VECTOR_NONE if there are no
139f2d2bf5dSjeremylt                  active inputs
140f2d2bf5dSjeremylt             v: Vector to sum in result of applying operator (must be distinct from u)
141f2d2bf5dSjeremylt                  or CEED_VECTOR_NONE if there are no active outputs
142f2d2bf5dSjeremylt             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
143f2d2bf5dSjeremylt
144f2d2bf5dSjeremylt        # libCEED call
145477729cfSJeremy L Thompson        err_code = lib.CeedOperatorApplyAdd(self._pointer[0], u._pointer[0], v._pointer[0],
146f2d2bf5dSjeremylt                                            request)
147477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
148f2d2bf5dSjeremylt
149*d99fa3c5SJeremy L Thompson    # Create Multigrid Level
150*d99fa3c5SJeremy L Thompson    def multigrid_create(self, p_mult_fine, rstr_coarse, basis_coarse):
151*d99fa3c5SJeremy L Thompson        """ Create a multigrid coarse operator and level transfer operators
152*d99fa3c5SJeremy L Thompson           for a CeedOperator with a Lagrange tensor basis for the active basis
153*d99fa3c5SJeremy L Thompson
154*d99fa3c5SJeremy L Thompson           Args:
155*d99fa3c5SJeremy L Thompson             p_mult_fine: L-vector multiplicity in parallel gather/scatter
156*d99fa3c5SJeremy L Thompson             basis_coarse: Coarse grid active vector basis
157*d99fa3c5SJeremy L Thompson             degree_coarse: Coarse grid basis polynomial order"""
158*d99fa3c5SJeremy L Thompson
159*d99fa3c5SJeremy L Thompson        # Operator pointers
160*d99fa3c5SJeremy L Thompson        opCoarsePointer = ffi.new("CeedOperator *")
161*d99fa3c5SJeremy L Thompson        opProlongPointer = ffi.new("CeedOperator *")
162*d99fa3c5SJeremy L Thompson        opRestrictPointer = ffi.new("CeedOperator *")
163*d99fa3c5SJeremy L Thompson
164*d99fa3c5SJeremy L Thompson        # libCEED call
165*d99fa3c5SJeremy L Thompson        lib.CeedOperatorMultigridLevelCreate(self._pointer[0],
166*d99fa3c5SJeremy L Thompson                                             p_mult_fine._pointer[0],
167*d99fa3c5SJeremy L Thompson                                             rstr_coarse._pointer[0],
168*d99fa3c5SJeremy L Thompson                                             basis_coarse._pointer[0],
169*d99fa3c5SJeremy L Thompson                                             opCoarsePointer,
170*d99fa3c5SJeremy L Thompson                                             opProlongPointer,
171*d99fa3c5SJeremy L Thompson                                             opRestrictPointer)
172*d99fa3c5SJeremy L Thompson
173*d99fa3c5SJeremy L Thompson        # Wrap operators
174*d99fa3c5SJeremy L Thompson        opCoarse = _OperatorWrap(
175*d99fa3c5SJeremy L Thompson            self._ceed, opCoarsePointer)
176*d99fa3c5SJeremy L Thompson        opProlong = _OperatorWrap(
177*d99fa3c5SJeremy L Thompson            self._ceed, opProlongPointer)
178*d99fa3c5SJeremy L Thompson        opRestrict = _OperatorWrap(
179*d99fa3c5SJeremy L Thompson            self._ceed, opRestrictPointer)
180*d99fa3c5SJeremy L Thompson
181*d99fa3c5SJeremy L Thompson        # Return
182*d99fa3c5SJeremy L Thompson        return [opCoarse, opProlong, opRestrict]
183*d99fa3c5SJeremy L Thompson
184*d99fa3c5SJeremy L Thompson    # Create Multigrid Level
185*d99fa3c5SJeremy L Thompson    def multigrid_create_tensor_h1(self, p_mult_fine, rstr_coarse, basis_coarse,
186*d99fa3c5SJeremy L Thompson                                   interp_C_to_F):
187*d99fa3c5SJeremy L Thompson        """ Create a multigrid coarse operator and level transfer operators
188*d99fa3c5SJeremy L Thompson           for a CeedOperator with a non-tensor basis for the active basis
189*d99fa3c5SJeremy L Thompson
190*d99fa3c5SJeremy L Thompson           Args:
191*d99fa3c5SJeremy L Thompson             p_mult_fine: L-vector multiplicity in parallel gather/scatter
192*d99fa3c5SJeremy L Thompson             rstr_coarse: Coarse grid restriction
193*d99fa3c5SJeremy L Thompson             basis_coarse: Coarse grid active vector basis
194*d99fa3c5SJeremy L Thompson             interp_C_to_F: Matrix for coarse to fine interpolation"""
195*d99fa3c5SJeremy L Thompson
196*d99fa3c5SJeremy L Thompson       # Setup arguments
197*d99fa3c5SJeremy L Thompson        interpCtoF_pointer = ffi.new("CeedScalar *")
198*d99fa3c5SJeremy L Thompson        interpCtoF_pointer = ffi.cast(
199*d99fa3c5SJeremy L Thompson            "CeedScalar *",
200*d99fa3c5SJeremy L Thompson            interp_C_to_F.__array_interface__['data'][0])
201*d99fa3c5SJeremy L Thompson
202*d99fa3c5SJeremy L Thompson        # Operator pointers
203*d99fa3c5SJeremy L Thompson        opCoarsePointer = ffi.new("CeedOperator *")
204*d99fa3c5SJeremy L Thompson        opProlongPointer = ffi.new("CeedOperator *")
205*d99fa3c5SJeremy L Thompson        opRestrictPointer = ffi.new("CeedOperator *")
206*d99fa3c5SJeremy L Thompson
207*d99fa3c5SJeremy L Thompson        # libCEED call
208*d99fa3c5SJeremy L Thompson        lib.CeedOperatorMultigridLevelCreateTensorH1(self._pointer[0],
209*d99fa3c5SJeremy L Thompson                                                     p_mult_fine._pointer[0],
210*d99fa3c5SJeremy L Thompson                                                     rstr_coarse._pointer[0],
211*d99fa3c5SJeremy L Thompson                                                     basis_coarse._pointer[0],
212*d99fa3c5SJeremy L Thompson                                                     interpCtoF_pointer,
213*d99fa3c5SJeremy L Thompson                                                     opCoarsePointer,
214*d99fa3c5SJeremy L Thompson                                                     opProlongPointer,
215*d99fa3c5SJeremy L Thompson                                                     opRestrictPointer)
216*d99fa3c5SJeremy L Thompson
217*d99fa3c5SJeremy L Thompson        # Wrap operators
218*d99fa3c5SJeremy L Thompson        opCoarse = _OperatorWrap(
219*d99fa3c5SJeremy L Thompson            self._ceed, opCoarsePointer)
220*d99fa3c5SJeremy L Thompson        opProlong = _OperatorWrap(
221*d99fa3c5SJeremy L Thompson            self._ceed, opProlongPointer)
222*d99fa3c5SJeremy L Thompson        opRestrict = _OperatorWrap(
223*d99fa3c5SJeremy L Thompson            self._ceed, opRestrictPointer)
224*d99fa3c5SJeremy L Thompson
225*d99fa3c5SJeremy L Thompson        # Return
226*d99fa3c5SJeremy L Thompson        return [opCoarse, opProlong, opRestrict]
227*d99fa3c5SJeremy L Thompson
228*d99fa3c5SJeremy L Thompson    # Create Multigrid Level
229*d99fa3c5SJeremy L Thompson    def multigrid_create_h1(self, p_mult_fine, rstr_coarse, basis_coarse,
230*d99fa3c5SJeremy L Thompson                            interp_C_to_F):
231*d99fa3c5SJeremy L Thompson        """ Create a multigrid coarse operator and level transfer operators
232*d99fa3c5SJeremy L Thompson           for a CeedOperator with a Lagrange tensor basis for the active basis
233*d99fa3c5SJeremy L Thompson
234*d99fa3c5SJeremy L Thompson           Args:
235*d99fa3c5SJeremy L Thompson             p_mult_fine: L-vector multiplicity in parallel gather/scatter
236*d99fa3c5SJeremy L Thompson             rstr_coarse: Coarse grid restriction
237*d99fa3c5SJeremy L Thompson             basis_coarse: Coarse grid active vector basis
238*d99fa3c5SJeremy L Thompson             interp_C_to_F: Matrix for coarse to fine interpolation"""
239*d99fa3c5SJeremy L Thompson
240*d99fa3c5SJeremy L Thompson       # Setup arguments
241*d99fa3c5SJeremy L Thompson        interpCtoF_pointer = ffi.new("CeedScalar *")
242*d99fa3c5SJeremy L Thompson        interpCtoF_pointer = ffi.cast(
243*d99fa3c5SJeremy L Thompson            "CeedScalar *",
244*d99fa3c5SJeremy L Thompson            interp_C_to_F.__array_interface__['data'][0])
245*d99fa3c5SJeremy L Thompson
246*d99fa3c5SJeremy L Thompson        # Operator pointers
247*d99fa3c5SJeremy L Thompson        opCoarsePointer = ffi.new("CeedOperator *")
248*d99fa3c5SJeremy L Thompson        opProlongPointer = ffi.new("CeedOperator *")
249*d99fa3c5SJeremy L Thompson        opRestrictPointer = ffi.new("CeedOperator *")
250*d99fa3c5SJeremy L Thompson
251*d99fa3c5SJeremy L Thompson        # libCEED call
252*d99fa3c5SJeremy L Thompson        lib.CeedOperatorMultigridLevelCreateH1(self._pointer[0],
253*d99fa3c5SJeremy L Thompson                                               p_mult_fine._pointer[0],
254*d99fa3c5SJeremy L Thompson                                               rstr_coarse._pointer[0],
255*d99fa3c5SJeremy L Thompson                                               basis_coarse._pointer[0],
256*d99fa3c5SJeremy L Thompson                                               interpCtoF_pointer,
257*d99fa3c5SJeremy L Thompson                                               opCoarsePointer,
258*d99fa3c5SJeremy L Thompson                                               opProlongPointer,
259*d99fa3c5SJeremy L Thompson                                               opRestrictPointer)
260*d99fa3c5SJeremy L Thompson
261*d99fa3c5SJeremy L Thompson        # Wrap operators
262*d99fa3c5SJeremy L Thompson        opCoarse = _OperatorWrap(
263*d99fa3c5SJeremy L Thompson            self._ceed, opCoarsePointer)
264*d99fa3c5SJeremy L Thompson        opProlong = _OperatorWrap(
265*d99fa3c5SJeremy L Thompson            self._ceed, opProlongPointer)
266*d99fa3c5SJeremy L Thompson        opRestrict = _OperatorWrap(
267*d99fa3c5SJeremy L Thompson            self._ceed, opRestrictPointer)
268*d99fa3c5SJeremy L Thompson
269*d99fa3c5SJeremy L Thompson        # Return
270*d99fa3c5SJeremy L Thompson        return [opCoarse, opProlong, opRestrict]
271*d99fa3c5SJeremy L Thompson
272*d99fa3c5SJeremy L Thompson
273f2d2bf5dSjeremylt# ------------------------------------------------------------------------------
2747a7b0fa3SJed Brown
2757a7b0fa3SJed Brown
276f2d2bf5dSjeremyltclass Operator(_OperatorBase):
277f2d2bf5dSjeremylt    """Ceed Operator: composed FE-type operations on vectors."""
278f2d2bf5dSjeremylt
279f2d2bf5dSjeremylt    # Constructor
280f2d2bf5dSjeremylt    def __init__(self, ceed, qf, dqf=None, dqfT=None):
281f2d2bf5dSjeremylt        # CeedOperator object
282f2d2bf5dSjeremylt        self._pointer = ffi.new("CeedOperator *")
283f2d2bf5dSjeremylt
284f2d2bf5dSjeremylt        # Reference to Ceed
285f2d2bf5dSjeremylt        self._ceed = ceed
286f2d2bf5dSjeremylt
287f2d2bf5dSjeremylt        # libCEED call
288477729cfSJeremy L Thompson        err_code = lib.CeedOperatorCreate(self._ceed._pointer[0], qf._pointer[0],
289f2d2bf5dSjeremylt                                          dqf._pointer[0] if dqf else ffi.NULL,
290f2d2bf5dSjeremylt                                          dqfT._pointer[0] if dqfT else ffi.NULL,
291f2d2bf5dSjeremylt                                          self._pointer)
292477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
293f2d2bf5dSjeremylt
294f2d2bf5dSjeremylt    # Add field to CeedOperator
295a8d32208Sjeremylt    def set_field(self, fieldname, restriction, basis, vector):
296f2d2bf5dSjeremylt        """Provide a field to an Operator for use by its QFunction.
297f2d2bf5dSjeremylt
298f2d2bf5dSjeremylt           Args:
299f2d2bf5dSjeremylt             fieldname: name of the field (to be matched with the same name used
300f2d2bf5dSjeremylt                          by QFunction)
301f2d2bf5dSjeremylt             restriction: ElemRestriction
302f2d2bf5dSjeremylt             basis: Basis in which the field resides or CEED_BASIS_COLLOCATED
303f2d2bf5dSjeremylt                      if collocated with quadrature points
304f2d2bf5dSjeremylt             vector: Vector to be used by Operator or CEED_VECTOR_ACTIVE
305f2d2bf5dSjeremylt                       if field is active or CEED_VECTOR_NONE if using
306a8d32208Sjeremylt                       CEED_EVAL_WEIGHT in the QFunction"""
307f2d2bf5dSjeremylt
308f2d2bf5dSjeremylt        # libCEED call
309f2d2bf5dSjeremylt        fieldnameAscii = ffi.new("char[]", fieldname.encode('ascii'))
310477729cfSJeremy L Thompson        err_code = lib.CeedOperatorSetField(self._pointer[0], fieldnameAscii,
311a8d32208Sjeremylt                                            restriction._pointer[0], basis._pointer[0],
312f2d2bf5dSjeremylt                                            vector._pointer[0])
313477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
314f2d2bf5dSjeremylt
315f2d2bf5dSjeremylt# ------------------------------------------------------------------------------
3167a7b0fa3SJed Brown
3177a7b0fa3SJed Brown
318f2d2bf5dSjeremyltclass CompositeOperator(_OperatorBase):
319f2d2bf5dSjeremylt    """Ceed Composite Operator: composition of multiple Operators."""
320f2d2bf5dSjeremylt
321f2d2bf5dSjeremylt    # Constructor
322f2d2bf5dSjeremylt    def __init__(self, ceed):
323f2d2bf5dSjeremylt        # CeedOperator object
324f2d2bf5dSjeremylt        self._pointer = ffi.new("CeedOperator *")
325f2d2bf5dSjeremylt
326f2d2bf5dSjeremylt        # Reference to Ceed
327f2d2bf5dSjeremylt        self._ceed = ceed
328f2d2bf5dSjeremylt        # libCEED call
329477729cfSJeremy L Thompson        err_code = lib.CeedCompositeOperatorCreate(
330477729cfSJeremy L Thompson            self._ceed._pointer[0], self._pointer)
331477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
332f2d2bf5dSjeremylt
333f2d2bf5dSjeremylt    # Add sub operators
334f2d2bf5dSjeremylt    def add_sub(self, subop):
335f2d2bf5dSjeremylt        """Add a sub-operator to a composite CeedOperator.
336f2d2bf5dSjeremylt
337f2d2bf5dSjeremylt           Args:
338f2d2bf5dSjeremylt             subop: sub-operator Operator"""
339f2d2bf5dSjeremylt
340f2d2bf5dSjeremylt        # libCEED call
341477729cfSJeremy L Thompson        err_code = lib.CeedCompositeOperatorAddSub(
342477729cfSJeremy L Thompson            self._pointer[0], subop._pointer[0])
343477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
344f2d2bf5dSjeremylt
345f2d2bf5dSjeremylt# ------------------------------------------------------------------------------
346*d99fa3c5SJeremy L Thompson
347*d99fa3c5SJeremy L Thompson
348*d99fa3c5SJeremy L Thompsonclass _OperatorWrap(Operator):
349*d99fa3c5SJeremy L Thompson    """Wrap a CeedOperator pointer in a Operator object."""
350*d99fa3c5SJeremy L Thompson
351*d99fa3c5SJeremy L Thompson    # Constructor
352*d99fa3c5SJeremy L Thompson    def __init__(self, ceed, pointer):
353*d99fa3c5SJeremy L Thompson        # CeedOperator object
354*d99fa3c5SJeremy L Thompson        self._pointer = pointer
355*d99fa3c5SJeremy L Thompson
356*d99fa3c5SJeremy L Thompson        # Reference to Ceed
357*d99fa3c5SJeremy L Thompson        self._ceed = ceed
358*d99fa3c5SJeremy L Thompson
359*d99fa3c5SJeremy L Thompson# ------------------------------------------------------------------------------
360