xref: /libCEED/python/ceed_operator.py (revision 3d8e882215d238700cdceb37404f76ca7fa24eaa)
1*3d8e8822SJeremy L Thompson# Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors
2*3d8e8822SJeremy L Thompson# All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3f2d2bf5dSjeremylt#
4*3d8e8822SJeremy L Thompson# SPDX-License-Identifier: BSD-2-Clause
5f2d2bf5dSjeremylt#
6*3d8e8822SJeremy L Thompson# This file is part of CEED:  http://github.com/ceed
7f2d2bf5dSjeremylt
8f2d2bf5dSjeremyltfrom _ceed_cffi import ffi, lib
9f2d2bf5dSjeremyltimport tempfile
10f2d2bf5dSjeremyltfrom abc import ABC
11f2d2bf5dSjeremyltfrom .ceed_constants import REQUEST_IMMEDIATE, REQUEST_ORDERED, NOTRANSPOSE
12f2d2bf5dSjeremylt
13f2d2bf5dSjeremylt# ------------------------------------------------------------------------------
147a7b0fa3SJed Brown
157a7b0fa3SJed Brown
16f2d2bf5dSjeremyltclass _OperatorBase(ABC):
17f2d2bf5dSjeremylt    """Ceed Operator: composed FE-type operations on vectors."""
18f2d2bf5dSjeremylt
19f2d2bf5dSjeremylt    # Destructor
20f2d2bf5dSjeremylt    def __del__(self):
21f2d2bf5dSjeremylt        # libCEED call
22477729cfSJeremy L Thompson        err_code = lib.CeedOperatorDestroy(self._pointer)
23477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
24f2d2bf5dSjeremylt
25f2d2bf5dSjeremylt    # Representation
26f2d2bf5dSjeremylt    def __repr__(self):
27f2d2bf5dSjeremylt        return "<CeedOperator instance at " + hex(id(self)) + ">"
28f2d2bf5dSjeremylt
29f2d2bf5dSjeremylt    # String conversion for print() to stdout
30f2d2bf5dSjeremylt    def __str__(self):
31f2d2bf5dSjeremylt        """View an Operator via print()."""
32f2d2bf5dSjeremylt
33f2d2bf5dSjeremylt        # libCEED call
34f2d2bf5dSjeremylt        with tempfile.NamedTemporaryFile() as key_file:
35f2d2bf5dSjeremylt            with open(key_file.name, 'r+') as stream_file:
36f2d2bf5dSjeremylt                stream = ffi.cast("FILE *", stream_file)
37f2d2bf5dSjeremylt
38477729cfSJeremy L Thompson                err_code = lib.CeedOperatorView(self._pointer[0], stream)
39477729cfSJeremy L Thompson                self._ceed._check_error(err_code)
40f2d2bf5dSjeremylt
41f2d2bf5dSjeremylt                stream_file.seek(0)
42f2d2bf5dSjeremylt                out_string = stream_file.read()
43f2d2bf5dSjeremylt
44f2d2bf5dSjeremylt        return out_string
45f2d2bf5dSjeremylt
4628d09c20SJeremy L Thompson    # Check Operator setup
4728d09c20SJeremy L Thompson    def check(self):
4828d09c20SJeremy L Thompson        """Check if a CeedOperator is ready to be used"""
4928d09c20SJeremy L Thompson        # libCEED call
5028d09c20SJeremy L Thompson        err_code = lib.CeedOperatorCheckReady(self._pointer[0])
5128d09c20SJeremy L Thompson        self._ceed._check_error(err_code)
5228d09c20SJeremy L Thompson
536397b31bSJeremy L Thompson    # Assemble linear diagonal
546397b31bSJeremy L Thompson    def linear_assemble_diagonal(self, d, request=REQUEST_IMMEDIATE):
556397b31bSJeremy L Thompson        """Assemble the diagonal of a square linear Operator
566397b31bSJeremy L Thompson
576397b31bSJeremy L Thompson           Args:
586397b31bSJeremy L Thompson             d: Vector to store assembled Operator diagonal
596397b31bSJeremy L Thompson             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
606397b31bSJeremy L Thompson
616397b31bSJeremy L Thompson        # libCEED call
62477729cfSJeremy L Thompson        err_code = lib.CeedOperatorLinearAssembleDiagonal(self._pointer[0],
636397b31bSJeremy L Thompson                                                          d._pointer[0], request)
64477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
656397b31bSJeremy L Thompson
666397b31bSJeremy L Thompson    # Assemble add linear diagonal
676397b31bSJeremy L Thompson    def linear_assemble_add_diagonal(self, d, request=REQUEST_IMMEDIATE):
686397b31bSJeremy L Thompson        """Sum the diagonal of a square linear Operator into a Vector
696397b31bSJeremy L Thompson
706397b31bSJeremy L Thompson           Args:
716397b31bSJeremy L Thompson             d: Vector to store assembled Operator diagonal
726397b31bSJeremy L Thompson             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
736397b31bSJeremy L Thompson
746397b31bSJeremy L Thompson        # libCEED call
75477729cfSJeremy L Thompson        err_code = lib.CeedOperatorLinearAssembleAddDiagonal(self._pointer[0],
766397b31bSJeremy L Thompson                                                             d._pointer[0], request)
77477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
786397b31bSJeremy L Thompson
796397b31bSJeremy L Thompson    # Assemble linear point block diagonal
800c9255dfSJeremy L Thompson    def linear_assemble_point_block_diagonal(
810c9255dfSJeremy L Thompson            self, d, request=REQUEST_IMMEDIATE):
820c9255dfSJeremy L Thompson        """Assemble the point block diagonal of a square linear Operator
836397b31bSJeremy L Thompson
846397b31bSJeremy L Thompson           Args:
856397b31bSJeremy L Thompson             d: Vector to store assembled Operator point block diagonal,
866397b31bSJeremy L Thompson                  provided in row-major form with an ncomp*ncomp block
876397b31bSJeremy L Thompson                  at each node
886397b31bSJeremy L Thompson             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
896397b31bSJeremy L Thompson
906397b31bSJeremy L Thompson        # libCEED call
91477729cfSJeremy L Thompson        err_code = lib.CeedOperatorLinearAssemblePointBlockDiagonal(self._pointer[0],
926397b31bSJeremy L Thompson                                                                    d._pointer[0], request)
93477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
946397b31bSJeremy L Thompson
956397b31bSJeremy L Thompson    # Assemble linear point block diagonal
960c9255dfSJeremy L Thompson    def linear_assemble_add_point_block_diagonal(
970c9255dfSJeremy L Thompson            self, d, request=REQUEST_IMMEDIATE):
980c9255dfSJeremy L Thompson        """Sum the point block diagonal of a square linear Operator into a Vector
996397b31bSJeremy L Thompson
1006397b31bSJeremy L Thompson           Args:
1016397b31bSJeremy L Thompson             d: Vector to store assembled Operator point block diagonal,
1026397b31bSJeremy L Thompson                  provided in row-major form with an ncomp*ncomp block
1036397b31bSJeremy L Thompson                  at each node
1046397b31bSJeremy L Thompson             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
1056397b31bSJeremy L Thompson
1066397b31bSJeremy L Thompson        # libCEED call
107477729cfSJeremy L Thompson        err_code = lib.CeedOperatorLinearAssembleAddPointBlockDiagonal(self._pointer[0],
1086397b31bSJeremy L Thompson                                                                       d._pointer[0], request)
109477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
1106397b31bSJeremy L Thompson
111f2d2bf5dSjeremylt    # Apply CeedOperator
112f2d2bf5dSjeremylt    def apply(self, u, v, request=REQUEST_IMMEDIATE):
113f2d2bf5dSjeremylt        """Apply Operator to a vector.
114f2d2bf5dSjeremylt
115f2d2bf5dSjeremylt           Args:
116f2d2bf5dSjeremylt             u: Vector containing input state or CEED_VECTOR_NONE if there are no
117f2d2bf5dSjeremylt                  active inputs
118f2d2bf5dSjeremylt             v: Vector to store result of applying operator (must be distinct from u)
119f2d2bf5dSjeremylt                  or CEED_VECTOR_NONE if there are no active outputs
120f2d2bf5dSjeremylt             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
121f2d2bf5dSjeremylt
122f2d2bf5dSjeremylt        # libCEED call
123477729cfSJeremy L Thompson        err_code = lib.CeedOperatorApply(self._pointer[0], u._pointer[0], v._pointer[0],
124f2d2bf5dSjeremylt                                         request)
125477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
126f2d2bf5dSjeremylt
127f2d2bf5dSjeremylt    # Apply CeedOperator
128f2d2bf5dSjeremylt    def apply_add(self, u, v, request=REQUEST_IMMEDIATE):
129f2d2bf5dSjeremylt        """Apply Operator to a vector and add result to output vector.
130f2d2bf5dSjeremylt
131f2d2bf5dSjeremylt           Args:
132f2d2bf5dSjeremylt             u: Vector containing input state or CEED_VECTOR_NONE if there are no
133f2d2bf5dSjeremylt                  active inputs
134f2d2bf5dSjeremylt             v: Vector to sum in result of applying operator (must be distinct from u)
135f2d2bf5dSjeremylt                  or CEED_VECTOR_NONE if there are no active outputs
136f2d2bf5dSjeremylt             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
137f2d2bf5dSjeremylt
138f2d2bf5dSjeremylt        # libCEED call
139477729cfSJeremy L Thompson        err_code = lib.CeedOperatorApplyAdd(self._pointer[0], u._pointer[0], v._pointer[0],
140f2d2bf5dSjeremylt                                            request)
141477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
142f2d2bf5dSjeremylt
143d99fa3c5SJeremy L Thompson    # Create Multigrid Level
144d99fa3c5SJeremy L Thompson    def multigrid_create(self, p_mult_fine, rstr_coarse, basis_coarse):
145d99fa3c5SJeremy L Thompson        """ Create a multigrid coarse operator and level transfer operators
146d99fa3c5SJeremy L Thompson           for a CeedOperator with a Lagrange tensor basis for the active basis
147d99fa3c5SJeremy L Thompson
148d99fa3c5SJeremy L Thompson           Args:
149d99fa3c5SJeremy L Thompson             p_mult_fine: L-vector multiplicity in parallel gather/scatter
150d99fa3c5SJeremy L Thompson             basis_coarse: Coarse grid active vector basis
151d99fa3c5SJeremy L Thompson             degree_coarse: Coarse grid basis polynomial order"""
152d99fa3c5SJeremy L Thompson
153d99fa3c5SJeremy L Thompson        # Operator pointers
154d99fa3c5SJeremy L Thompson        opCoarsePointer = ffi.new("CeedOperator *")
155d99fa3c5SJeremy L Thompson        opProlongPointer = ffi.new("CeedOperator *")
156d99fa3c5SJeremy L Thompson        opRestrictPointer = ffi.new("CeedOperator *")
157d99fa3c5SJeremy L Thompson
158d99fa3c5SJeremy L Thompson        # libCEED call
159d99fa3c5SJeremy L Thompson        lib.CeedOperatorMultigridLevelCreate(self._pointer[0],
160d99fa3c5SJeremy L Thompson                                             p_mult_fine._pointer[0],
161d99fa3c5SJeremy L Thompson                                             rstr_coarse._pointer[0],
162d99fa3c5SJeremy L Thompson                                             basis_coarse._pointer[0],
163d99fa3c5SJeremy L Thompson                                             opCoarsePointer,
164d99fa3c5SJeremy L Thompson                                             opProlongPointer,
165d99fa3c5SJeremy L Thompson                                             opRestrictPointer)
166d99fa3c5SJeremy L Thompson
167d99fa3c5SJeremy L Thompson        # Wrap operators
168d99fa3c5SJeremy L Thompson        opCoarse = _OperatorWrap(
169d99fa3c5SJeremy L Thompson            self._ceed, opCoarsePointer)
170d99fa3c5SJeremy L Thompson        opProlong = _OperatorWrap(
171d99fa3c5SJeremy L Thompson            self._ceed, opProlongPointer)
172d99fa3c5SJeremy L Thompson        opRestrict = _OperatorWrap(
173d99fa3c5SJeremy L Thompson            self._ceed, opRestrictPointer)
174d99fa3c5SJeremy L Thompson
175d99fa3c5SJeremy L Thompson        # Return
176d99fa3c5SJeremy L Thompson        return [opCoarse, opProlong, opRestrict]
177d99fa3c5SJeremy L Thompson
178d99fa3c5SJeremy L Thompson    # Create Multigrid Level
179d99fa3c5SJeremy L Thompson    def multigrid_create_tensor_h1(self, p_mult_fine, rstr_coarse, basis_coarse,
180d99fa3c5SJeremy L Thompson                                   interp_C_to_F):
181d99fa3c5SJeremy L Thompson        """ Create a multigrid coarse operator and level transfer operators
182d99fa3c5SJeremy L Thompson           for a CeedOperator with a non-tensor basis for the active basis
183d99fa3c5SJeremy L Thompson
184d99fa3c5SJeremy L Thompson           Args:
185d99fa3c5SJeremy L Thompson             p_mult_fine: L-vector multiplicity in parallel gather/scatter
186d99fa3c5SJeremy L Thompson             rstr_coarse: Coarse grid restriction
187d99fa3c5SJeremy L Thompson             basis_coarse: Coarse grid active vector basis
188d99fa3c5SJeremy L Thompson             interp_C_to_F: Matrix for coarse to fine interpolation"""
189d99fa3c5SJeremy L Thompson
190d99fa3c5SJeremy L Thompson       # Setup arguments
191d99fa3c5SJeremy L Thompson        interpCtoF_pointer = ffi.new("CeedScalar *")
192d99fa3c5SJeremy L Thompson        interpCtoF_pointer = ffi.cast(
193d99fa3c5SJeremy L Thompson            "CeedScalar *",
194d99fa3c5SJeremy L Thompson            interp_C_to_F.__array_interface__['data'][0])
195d99fa3c5SJeremy L Thompson
196d99fa3c5SJeremy L Thompson        # Operator pointers
197d99fa3c5SJeremy L Thompson        opCoarsePointer = ffi.new("CeedOperator *")
198d99fa3c5SJeremy L Thompson        opProlongPointer = ffi.new("CeedOperator *")
199d99fa3c5SJeremy L Thompson        opRestrictPointer = ffi.new("CeedOperator *")
200d99fa3c5SJeremy L Thompson
201d99fa3c5SJeremy L Thompson        # libCEED call
202d99fa3c5SJeremy L Thompson        lib.CeedOperatorMultigridLevelCreateTensorH1(self._pointer[0],
203d99fa3c5SJeremy L Thompson                                                     p_mult_fine._pointer[0],
204d99fa3c5SJeremy L Thompson                                                     rstr_coarse._pointer[0],
205d99fa3c5SJeremy L Thompson                                                     basis_coarse._pointer[0],
206d99fa3c5SJeremy L Thompson                                                     interpCtoF_pointer,
207d99fa3c5SJeremy L Thompson                                                     opCoarsePointer,
208d99fa3c5SJeremy L Thompson                                                     opProlongPointer,
209d99fa3c5SJeremy L Thompson                                                     opRestrictPointer)
210d99fa3c5SJeremy L Thompson
211d99fa3c5SJeremy L Thompson        # Wrap operators
212d99fa3c5SJeremy L Thompson        opCoarse = _OperatorWrap(
213d99fa3c5SJeremy L Thompson            self._ceed, opCoarsePointer)
214d99fa3c5SJeremy L Thompson        opProlong = _OperatorWrap(
215d99fa3c5SJeremy L Thompson            self._ceed, opProlongPointer)
216d99fa3c5SJeremy L Thompson        opRestrict = _OperatorWrap(
217d99fa3c5SJeremy L Thompson            self._ceed, opRestrictPointer)
218d99fa3c5SJeremy L Thompson
219d99fa3c5SJeremy L Thompson        # Return
220d99fa3c5SJeremy L Thompson        return [opCoarse, opProlong, opRestrict]
221d99fa3c5SJeremy L Thompson
222d99fa3c5SJeremy L Thompson    # Create Multigrid Level
223d99fa3c5SJeremy L Thompson    def multigrid_create_h1(self, p_mult_fine, rstr_coarse, basis_coarse,
224d99fa3c5SJeremy L Thompson                            interp_C_to_F):
225d99fa3c5SJeremy L Thompson        """ Create a multigrid coarse operator and level transfer operators
226d99fa3c5SJeremy L Thompson           for a CeedOperator with a Lagrange tensor basis for the active basis
227d99fa3c5SJeremy L Thompson
228d99fa3c5SJeremy L Thompson           Args:
229d99fa3c5SJeremy L Thompson             p_mult_fine: L-vector multiplicity in parallel gather/scatter
230d99fa3c5SJeremy L Thompson             rstr_coarse: Coarse grid restriction
231d99fa3c5SJeremy L Thompson             basis_coarse: Coarse grid active vector basis
232d99fa3c5SJeremy L Thompson             interp_C_to_F: Matrix for coarse to fine interpolation"""
233d99fa3c5SJeremy L Thompson
234d99fa3c5SJeremy L Thompson       # Setup arguments
235d99fa3c5SJeremy L Thompson        interpCtoF_pointer = ffi.new("CeedScalar *")
236d99fa3c5SJeremy L Thompson        interpCtoF_pointer = ffi.cast(
237d99fa3c5SJeremy L Thompson            "CeedScalar *",
238d99fa3c5SJeremy L Thompson            interp_C_to_F.__array_interface__['data'][0])
239d99fa3c5SJeremy L Thompson
240d99fa3c5SJeremy L Thompson        # Operator pointers
241d99fa3c5SJeremy L Thompson        opCoarsePointer = ffi.new("CeedOperator *")
242d99fa3c5SJeremy L Thompson        opProlongPointer = ffi.new("CeedOperator *")
243d99fa3c5SJeremy L Thompson        opRestrictPointer = ffi.new("CeedOperator *")
244d99fa3c5SJeremy L Thompson
245d99fa3c5SJeremy L Thompson        # libCEED call
246d99fa3c5SJeremy L Thompson        lib.CeedOperatorMultigridLevelCreateH1(self._pointer[0],
247d99fa3c5SJeremy L Thompson                                               p_mult_fine._pointer[0],
248d99fa3c5SJeremy L Thompson                                               rstr_coarse._pointer[0],
249d99fa3c5SJeremy L Thompson                                               basis_coarse._pointer[0],
250d99fa3c5SJeremy L Thompson                                               interpCtoF_pointer,
251d99fa3c5SJeremy L Thompson                                               opCoarsePointer,
252d99fa3c5SJeremy L Thompson                                               opProlongPointer,
253d99fa3c5SJeremy L Thompson                                               opRestrictPointer)
254d99fa3c5SJeremy L Thompson
255d99fa3c5SJeremy L Thompson        # Wrap operators
256d99fa3c5SJeremy L Thompson        opCoarse = _OperatorWrap(
257d99fa3c5SJeremy L Thompson            self._ceed, opCoarsePointer)
258d99fa3c5SJeremy L Thompson        opProlong = _OperatorWrap(
259d99fa3c5SJeremy L Thompson            self._ceed, opProlongPointer)
260d99fa3c5SJeremy L Thompson        opRestrict = _OperatorWrap(
261d99fa3c5SJeremy L Thompson            self._ceed, opRestrictPointer)
262d99fa3c5SJeremy L Thompson
263d99fa3c5SJeremy L Thompson        # Return
264d99fa3c5SJeremy L Thompson        return [opCoarse, opProlong, opRestrict]
265d99fa3c5SJeremy L Thompson
266d99fa3c5SJeremy L Thompson
267f2d2bf5dSjeremylt# ------------------------------------------------------------------------------
2687a7b0fa3SJed Brown
2697a7b0fa3SJed Brown
270f2d2bf5dSjeremyltclass Operator(_OperatorBase):
271f2d2bf5dSjeremylt    """Ceed Operator: composed FE-type operations on vectors."""
272f2d2bf5dSjeremylt
273f2d2bf5dSjeremylt    # Constructor
274f2d2bf5dSjeremylt    def __init__(self, ceed, qf, dqf=None, dqfT=None):
275f2d2bf5dSjeremylt        # CeedOperator object
276f2d2bf5dSjeremylt        self._pointer = ffi.new("CeedOperator *")
277f2d2bf5dSjeremylt
278f2d2bf5dSjeremylt        # Reference to Ceed
279f2d2bf5dSjeremylt        self._ceed = ceed
280f2d2bf5dSjeremylt
281f2d2bf5dSjeremylt        # libCEED call
282477729cfSJeremy L Thompson        err_code = lib.CeedOperatorCreate(self._ceed._pointer[0], qf._pointer[0],
283f2d2bf5dSjeremylt                                          dqf._pointer[0] if dqf else ffi.NULL,
284f2d2bf5dSjeremylt                                          dqfT._pointer[0] if dqfT else ffi.NULL,
285f2d2bf5dSjeremylt                                          self._pointer)
286477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
287f2d2bf5dSjeremylt
288f2d2bf5dSjeremylt    # Add field to CeedOperator
289a8d32208Sjeremylt    def set_field(self, fieldname, restriction, basis, vector):
290f2d2bf5dSjeremylt        """Provide a field to an Operator for use by its QFunction.
291f2d2bf5dSjeremylt
292f2d2bf5dSjeremylt           Args:
293f2d2bf5dSjeremylt             fieldname: name of the field (to be matched with the same name used
294f2d2bf5dSjeremylt                          by QFunction)
295f2d2bf5dSjeremylt             restriction: ElemRestriction
296f2d2bf5dSjeremylt             basis: Basis in which the field resides or CEED_BASIS_COLLOCATED
297f2d2bf5dSjeremylt                      if collocated with quadrature points
298f2d2bf5dSjeremylt             vector: Vector to be used by Operator or CEED_VECTOR_ACTIVE
299f2d2bf5dSjeremylt                       if field is active or CEED_VECTOR_NONE if using
300a8d32208Sjeremylt                       CEED_EVAL_WEIGHT in the QFunction"""
301f2d2bf5dSjeremylt
302f2d2bf5dSjeremylt        # libCEED call
303f2d2bf5dSjeremylt        fieldnameAscii = ffi.new("char[]", fieldname.encode('ascii'))
304477729cfSJeremy L Thompson        err_code = lib.CeedOperatorSetField(self._pointer[0], fieldnameAscii,
305a8d32208Sjeremylt                                            restriction._pointer[0], basis._pointer[0],
306f2d2bf5dSjeremylt                                            vector._pointer[0])
307477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
308f2d2bf5dSjeremylt
309f2d2bf5dSjeremylt# ------------------------------------------------------------------------------
3107a7b0fa3SJed Brown
3117a7b0fa3SJed Brown
312f2d2bf5dSjeremyltclass CompositeOperator(_OperatorBase):
313f2d2bf5dSjeremylt    """Ceed Composite Operator: composition of multiple Operators."""
314f2d2bf5dSjeremylt
315f2d2bf5dSjeremylt    # Constructor
316f2d2bf5dSjeremylt    def __init__(self, ceed):
317f2d2bf5dSjeremylt        # CeedOperator object
318f2d2bf5dSjeremylt        self._pointer = ffi.new("CeedOperator *")
319f2d2bf5dSjeremylt
320f2d2bf5dSjeremylt        # Reference to Ceed
321f2d2bf5dSjeremylt        self._ceed = ceed
322f2d2bf5dSjeremylt        # libCEED call
323477729cfSJeremy L Thompson        err_code = lib.CeedCompositeOperatorCreate(
324477729cfSJeremy L Thompson            self._ceed._pointer[0], self._pointer)
325477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
326f2d2bf5dSjeremylt
327f2d2bf5dSjeremylt    # Add sub operators
328f2d2bf5dSjeremylt    def add_sub(self, subop):
329f2d2bf5dSjeremylt        """Add a sub-operator to a composite CeedOperator.
330f2d2bf5dSjeremylt
331f2d2bf5dSjeremylt           Args:
332f2d2bf5dSjeremylt             subop: sub-operator Operator"""
333f2d2bf5dSjeremylt
334f2d2bf5dSjeremylt        # libCEED call
335477729cfSJeremy L Thompson        err_code = lib.CeedCompositeOperatorAddSub(
336477729cfSJeremy L Thompson            self._pointer[0], subop._pointer[0])
337477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
338f2d2bf5dSjeremylt
339f2d2bf5dSjeremylt# ------------------------------------------------------------------------------
340d99fa3c5SJeremy L Thompson
341d99fa3c5SJeremy L Thompson
342d99fa3c5SJeremy L Thompsonclass _OperatorWrap(Operator):
343d99fa3c5SJeremy L Thompson    """Wrap a CeedOperator pointer in a Operator object."""
344d99fa3c5SJeremy L Thompson
345d99fa3c5SJeremy L Thompson    # Constructor
346d99fa3c5SJeremy L Thompson    def __init__(self, ceed, pointer):
347d99fa3c5SJeremy L Thompson        # CeedOperator object
348d99fa3c5SJeremy L Thompson        self._pointer = pointer
349d99fa3c5SJeremy L Thompson
350d99fa3c5SJeremy L Thompson        # Reference to Ceed
351d99fa3c5SJeremy L Thompson        self._ceed = ceed
352d99fa3c5SJeremy L Thompson
353d99fa3c5SJeremy L Thompson# ------------------------------------------------------------------------------
354