xref: /libCEED/python/ceed_operator.py (revision ea6b58218a3c4883c2efd66165b4d6b684f89f5a)
13d8e8822SJeremy L Thompson# Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors
23d8e8822SJeremy L Thompson# All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
3f2d2bf5dSjeremylt#
43d8e8822SJeremy L Thompson# SPDX-License-Identifier: BSD-2-Clause
5f2d2bf5dSjeremylt#
63d8e8822SJeremy 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
111*ea6b5821SJeremy L Thompson    # Set name
112*ea6b5821SJeremy L Thompson    def name(self, name):
113*ea6b5821SJeremy L Thompson        """Set name of Operator for print output
114*ea6b5821SJeremy L Thompson
115*ea6b5821SJeremy L Thompson           Args:
116*ea6b5821SJeremy L Thompson             name: Name to set"""
117*ea6b5821SJeremy L Thompson
118*ea6b5821SJeremy L Thompson        name = ffi.new("char[]", name.encode('ascii'))
119*ea6b5821SJeremy L Thompson        err_code = lib.CeedOperatorSetName(self._pointer[0], name)
120*ea6b5821SJeremy L Thompson        self._ceed._check_error(err_code)
121*ea6b5821SJeremy L Thompson
122f2d2bf5dSjeremylt    # Apply CeedOperator
123f2d2bf5dSjeremylt    def apply(self, u, v, request=REQUEST_IMMEDIATE):
124f2d2bf5dSjeremylt        """Apply Operator to a vector.
125f2d2bf5dSjeremylt
126f2d2bf5dSjeremylt           Args:
127f2d2bf5dSjeremylt             u: Vector containing input state or CEED_VECTOR_NONE if there are no
128f2d2bf5dSjeremylt                  active inputs
129f2d2bf5dSjeremylt             v: Vector to store result of applying operator (must be distinct from u)
130f2d2bf5dSjeremylt                  or CEED_VECTOR_NONE if there are no active outputs
131f2d2bf5dSjeremylt             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
132f2d2bf5dSjeremylt
133f2d2bf5dSjeremylt        # libCEED call
134477729cfSJeremy L Thompson        err_code = lib.CeedOperatorApply(self._pointer[0], u._pointer[0], v._pointer[0],
135f2d2bf5dSjeremylt                                         request)
136477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
137f2d2bf5dSjeremylt
138f2d2bf5dSjeremylt    # Apply CeedOperator
139f2d2bf5dSjeremylt    def apply_add(self, u, v, request=REQUEST_IMMEDIATE):
140f2d2bf5dSjeremylt        """Apply Operator to a vector and add result to output vector.
141f2d2bf5dSjeremylt
142f2d2bf5dSjeremylt           Args:
143f2d2bf5dSjeremylt             u: Vector containing input state or CEED_VECTOR_NONE if there are no
144f2d2bf5dSjeremylt                  active inputs
145f2d2bf5dSjeremylt             v: Vector to sum in result of applying operator (must be distinct from u)
146f2d2bf5dSjeremylt                  or CEED_VECTOR_NONE if there are no active outputs
147f2d2bf5dSjeremylt             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
148f2d2bf5dSjeremylt
149f2d2bf5dSjeremylt        # libCEED call
150477729cfSJeremy L Thompson        err_code = lib.CeedOperatorApplyAdd(self._pointer[0], u._pointer[0], v._pointer[0],
151f2d2bf5dSjeremylt                                            request)
152477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
153f2d2bf5dSjeremylt
154d99fa3c5SJeremy L Thompson    # Create Multigrid Level
155d99fa3c5SJeremy L Thompson    def multigrid_create(self, p_mult_fine, rstr_coarse, basis_coarse):
156d99fa3c5SJeremy L Thompson        """ Create a multigrid coarse operator and level transfer operators
157d99fa3c5SJeremy L Thompson           for a CeedOperator with a Lagrange tensor basis for the active basis
158d99fa3c5SJeremy L Thompson
159d99fa3c5SJeremy L Thompson           Args:
160d99fa3c5SJeremy L Thompson             p_mult_fine: L-vector multiplicity in parallel gather/scatter
161d99fa3c5SJeremy L Thompson             basis_coarse: Coarse grid active vector basis
162d99fa3c5SJeremy L Thompson             degree_coarse: Coarse grid basis polynomial order"""
163d99fa3c5SJeremy L Thompson
164d99fa3c5SJeremy L Thompson        # Operator pointers
165d99fa3c5SJeremy L Thompson        opCoarsePointer = ffi.new("CeedOperator *")
166d99fa3c5SJeremy L Thompson        opProlongPointer = ffi.new("CeedOperator *")
167d99fa3c5SJeremy L Thompson        opRestrictPointer = ffi.new("CeedOperator *")
168d99fa3c5SJeremy L Thompson
169d99fa3c5SJeremy L Thompson        # libCEED call
170d99fa3c5SJeremy L Thompson        lib.CeedOperatorMultigridLevelCreate(self._pointer[0],
171d99fa3c5SJeremy L Thompson                                             p_mult_fine._pointer[0],
172d99fa3c5SJeremy L Thompson                                             rstr_coarse._pointer[0],
173d99fa3c5SJeremy L Thompson                                             basis_coarse._pointer[0],
174d99fa3c5SJeremy L Thompson                                             opCoarsePointer,
175d99fa3c5SJeremy L Thompson                                             opProlongPointer,
176d99fa3c5SJeremy L Thompson                                             opRestrictPointer)
177d99fa3c5SJeremy L Thompson
178d99fa3c5SJeremy L Thompson        # Wrap operators
179d99fa3c5SJeremy L Thompson        opCoarse = _OperatorWrap(
180d99fa3c5SJeremy L Thompson            self._ceed, opCoarsePointer)
181d99fa3c5SJeremy L Thompson        opProlong = _OperatorWrap(
182d99fa3c5SJeremy L Thompson            self._ceed, opProlongPointer)
183d99fa3c5SJeremy L Thompson        opRestrict = _OperatorWrap(
184d99fa3c5SJeremy L Thompson            self._ceed, opRestrictPointer)
185d99fa3c5SJeremy L Thompson
186d99fa3c5SJeremy L Thompson        # Return
187d99fa3c5SJeremy L Thompson        return [opCoarse, opProlong, opRestrict]
188d99fa3c5SJeremy L Thompson
189d99fa3c5SJeremy L Thompson    # Create Multigrid Level
190d99fa3c5SJeremy L Thompson    def multigrid_create_tensor_h1(self, p_mult_fine, rstr_coarse, basis_coarse,
191d99fa3c5SJeremy L Thompson                                   interp_C_to_F):
192d99fa3c5SJeremy L Thompson        """ Create a multigrid coarse operator and level transfer operators
193d99fa3c5SJeremy L Thompson           for a CeedOperator with a non-tensor basis for the active basis
194d99fa3c5SJeremy L Thompson
195d99fa3c5SJeremy L Thompson           Args:
196d99fa3c5SJeremy L Thompson             p_mult_fine: L-vector multiplicity in parallel gather/scatter
197d99fa3c5SJeremy L Thompson             rstr_coarse: Coarse grid restriction
198d99fa3c5SJeremy L Thompson             basis_coarse: Coarse grid active vector basis
199d99fa3c5SJeremy L Thompson             interp_C_to_F: Matrix for coarse to fine interpolation"""
200d99fa3c5SJeremy L Thompson
201d99fa3c5SJeremy L Thompson       # Setup arguments
202d99fa3c5SJeremy L Thompson        interpCtoF_pointer = ffi.new("CeedScalar *")
203d99fa3c5SJeremy L Thompson        interpCtoF_pointer = ffi.cast(
204d99fa3c5SJeremy L Thompson            "CeedScalar *",
205d99fa3c5SJeremy L Thompson            interp_C_to_F.__array_interface__['data'][0])
206d99fa3c5SJeremy L Thompson
207d99fa3c5SJeremy L Thompson        # Operator pointers
208d99fa3c5SJeremy L Thompson        opCoarsePointer = ffi.new("CeedOperator *")
209d99fa3c5SJeremy L Thompson        opProlongPointer = ffi.new("CeedOperator *")
210d99fa3c5SJeremy L Thompson        opRestrictPointer = ffi.new("CeedOperator *")
211d99fa3c5SJeremy L Thompson
212d99fa3c5SJeremy L Thompson        # libCEED call
213d99fa3c5SJeremy L Thompson        lib.CeedOperatorMultigridLevelCreateTensorH1(self._pointer[0],
214d99fa3c5SJeremy L Thompson                                                     p_mult_fine._pointer[0],
215d99fa3c5SJeremy L Thompson                                                     rstr_coarse._pointer[0],
216d99fa3c5SJeremy L Thompson                                                     basis_coarse._pointer[0],
217d99fa3c5SJeremy L Thompson                                                     interpCtoF_pointer,
218d99fa3c5SJeremy L Thompson                                                     opCoarsePointer,
219d99fa3c5SJeremy L Thompson                                                     opProlongPointer,
220d99fa3c5SJeremy L Thompson                                                     opRestrictPointer)
221d99fa3c5SJeremy L Thompson
222d99fa3c5SJeremy L Thompson        # Wrap operators
223d99fa3c5SJeremy L Thompson        opCoarse = _OperatorWrap(
224d99fa3c5SJeremy L Thompson            self._ceed, opCoarsePointer)
225d99fa3c5SJeremy L Thompson        opProlong = _OperatorWrap(
226d99fa3c5SJeremy L Thompson            self._ceed, opProlongPointer)
227d99fa3c5SJeremy L Thompson        opRestrict = _OperatorWrap(
228d99fa3c5SJeremy L Thompson            self._ceed, opRestrictPointer)
229d99fa3c5SJeremy L Thompson
230d99fa3c5SJeremy L Thompson        # Return
231d99fa3c5SJeremy L Thompson        return [opCoarse, opProlong, opRestrict]
232d99fa3c5SJeremy L Thompson
233d99fa3c5SJeremy L Thompson    # Create Multigrid Level
234d99fa3c5SJeremy L Thompson    def multigrid_create_h1(self, p_mult_fine, rstr_coarse, basis_coarse,
235d99fa3c5SJeremy L Thompson                            interp_C_to_F):
236d99fa3c5SJeremy L Thompson        """ Create a multigrid coarse operator and level transfer operators
237d99fa3c5SJeremy L Thompson           for a CeedOperator with a Lagrange tensor basis for the active basis
238d99fa3c5SJeremy L Thompson
239d99fa3c5SJeremy L Thompson           Args:
240d99fa3c5SJeremy L Thompson             p_mult_fine: L-vector multiplicity in parallel gather/scatter
241d99fa3c5SJeremy L Thompson             rstr_coarse: Coarse grid restriction
242d99fa3c5SJeremy L Thompson             basis_coarse: Coarse grid active vector basis
243d99fa3c5SJeremy L Thompson             interp_C_to_F: Matrix for coarse to fine interpolation"""
244d99fa3c5SJeremy L Thompson
245d99fa3c5SJeremy L Thompson       # Setup arguments
246d99fa3c5SJeremy L Thompson        interpCtoF_pointer = ffi.new("CeedScalar *")
247d99fa3c5SJeremy L Thompson        interpCtoF_pointer = ffi.cast(
248d99fa3c5SJeremy L Thompson            "CeedScalar *",
249d99fa3c5SJeremy L Thompson            interp_C_to_F.__array_interface__['data'][0])
250d99fa3c5SJeremy L Thompson
251d99fa3c5SJeremy L Thompson        # Operator pointers
252d99fa3c5SJeremy L Thompson        opCoarsePointer = ffi.new("CeedOperator *")
253d99fa3c5SJeremy L Thompson        opProlongPointer = ffi.new("CeedOperator *")
254d99fa3c5SJeremy L Thompson        opRestrictPointer = ffi.new("CeedOperator *")
255d99fa3c5SJeremy L Thompson
256d99fa3c5SJeremy L Thompson        # libCEED call
257d99fa3c5SJeremy L Thompson        lib.CeedOperatorMultigridLevelCreateH1(self._pointer[0],
258d99fa3c5SJeremy L Thompson                                               p_mult_fine._pointer[0],
259d99fa3c5SJeremy L Thompson                                               rstr_coarse._pointer[0],
260d99fa3c5SJeremy L Thompson                                               basis_coarse._pointer[0],
261d99fa3c5SJeremy L Thompson                                               interpCtoF_pointer,
262d99fa3c5SJeremy L Thompson                                               opCoarsePointer,
263d99fa3c5SJeremy L Thompson                                               opProlongPointer,
264d99fa3c5SJeremy L Thompson                                               opRestrictPointer)
265d99fa3c5SJeremy L Thompson
266d99fa3c5SJeremy L Thompson        # Wrap operators
267d99fa3c5SJeremy L Thompson        opCoarse = _OperatorWrap(
268d99fa3c5SJeremy L Thompson            self._ceed, opCoarsePointer)
269d99fa3c5SJeremy L Thompson        opProlong = _OperatorWrap(
270d99fa3c5SJeremy L Thompson            self._ceed, opProlongPointer)
271d99fa3c5SJeremy L Thompson        opRestrict = _OperatorWrap(
272d99fa3c5SJeremy L Thompson            self._ceed, opRestrictPointer)
273d99fa3c5SJeremy L Thompson
274d99fa3c5SJeremy L Thompson        # Return
275d99fa3c5SJeremy L Thompson        return [opCoarse, opProlong, opRestrict]
276d99fa3c5SJeremy L Thompson
277d99fa3c5SJeremy L Thompson
278f2d2bf5dSjeremylt# ------------------------------------------------------------------------------
2797a7b0fa3SJed Brown
2807a7b0fa3SJed Brown
281f2d2bf5dSjeremyltclass Operator(_OperatorBase):
282f2d2bf5dSjeremylt    """Ceed Operator: composed FE-type operations on vectors."""
283f2d2bf5dSjeremylt
284f2d2bf5dSjeremylt    # Constructor
285f2d2bf5dSjeremylt    def __init__(self, ceed, qf, dqf=None, dqfT=None):
286f2d2bf5dSjeremylt        # CeedOperator object
287f2d2bf5dSjeremylt        self._pointer = ffi.new("CeedOperator *")
288f2d2bf5dSjeremylt
289f2d2bf5dSjeremylt        # Reference to Ceed
290f2d2bf5dSjeremylt        self._ceed = ceed
291f2d2bf5dSjeremylt
292f2d2bf5dSjeremylt        # libCEED call
293477729cfSJeremy L Thompson        err_code = lib.CeedOperatorCreate(self._ceed._pointer[0], qf._pointer[0],
294f2d2bf5dSjeremylt                                          dqf._pointer[0] if dqf else ffi.NULL,
295f2d2bf5dSjeremylt                                          dqfT._pointer[0] if dqfT else ffi.NULL,
296f2d2bf5dSjeremylt                                          self._pointer)
297477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
298f2d2bf5dSjeremylt
299f2d2bf5dSjeremylt    # Add field to CeedOperator
300a8d32208Sjeremylt    def set_field(self, fieldname, restriction, basis, vector):
301f2d2bf5dSjeremylt        """Provide a field to an Operator for use by its QFunction.
302f2d2bf5dSjeremylt
303f2d2bf5dSjeremylt           Args:
304f2d2bf5dSjeremylt             fieldname: name of the field (to be matched with the same name used
305f2d2bf5dSjeremylt                          by QFunction)
306f2d2bf5dSjeremylt             restriction: ElemRestriction
307f2d2bf5dSjeremylt             basis: Basis in which the field resides or CEED_BASIS_COLLOCATED
308f2d2bf5dSjeremylt                      if collocated with quadrature points
309f2d2bf5dSjeremylt             vector: Vector to be used by Operator or CEED_VECTOR_ACTIVE
310f2d2bf5dSjeremylt                       if field is active or CEED_VECTOR_NONE if using
311a8d32208Sjeremylt                       CEED_EVAL_WEIGHT in the QFunction"""
312f2d2bf5dSjeremylt
313f2d2bf5dSjeremylt        # libCEED call
314f2d2bf5dSjeremylt        fieldnameAscii = ffi.new("char[]", fieldname.encode('ascii'))
315477729cfSJeremy L Thompson        err_code = lib.CeedOperatorSetField(self._pointer[0], fieldnameAscii,
316a8d32208Sjeremylt                                            restriction._pointer[0], basis._pointer[0],
317f2d2bf5dSjeremylt                                            vector._pointer[0])
318477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
319f2d2bf5dSjeremylt
320f2d2bf5dSjeremylt# ------------------------------------------------------------------------------
3217a7b0fa3SJed Brown
3227a7b0fa3SJed Brown
323f2d2bf5dSjeremyltclass CompositeOperator(_OperatorBase):
324f2d2bf5dSjeremylt    """Ceed Composite Operator: composition of multiple Operators."""
325f2d2bf5dSjeremylt
326f2d2bf5dSjeremylt    # Constructor
327f2d2bf5dSjeremylt    def __init__(self, ceed):
328f2d2bf5dSjeremylt        # CeedOperator object
329f2d2bf5dSjeremylt        self._pointer = ffi.new("CeedOperator *")
330f2d2bf5dSjeremylt
331f2d2bf5dSjeremylt        # Reference to Ceed
332f2d2bf5dSjeremylt        self._ceed = ceed
333f2d2bf5dSjeremylt        # libCEED call
334477729cfSJeremy L Thompson        err_code = lib.CeedCompositeOperatorCreate(
335477729cfSJeremy L Thompson            self._ceed._pointer[0], self._pointer)
336477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
337f2d2bf5dSjeremylt
338f2d2bf5dSjeremylt    # Add sub operators
339f2d2bf5dSjeremylt    def add_sub(self, subop):
340f2d2bf5dSjeremylt        """Add a sub-operator to a composite CeedOperator.
341f2d2bf5dSjeremylt
342f2d2bf5dSjeremylt           Args:
343f2d2bf5dSjeremylt             subop: sub-operator Operator"""
344f2d2bf5dSjeremylt
345f2d2bf5dSjeremylt        # libCEED call
346477729cfSJeremy L Thompson        err_code = lib.CeedCompositeOperatorAddSub(
347477729cfSJeremy L Thompson            self._pointer[0], subop._pointer[0])
348477729cfSJeremy L Thompson        self._ceed._check_error(err_code)
349f2d2bf5dSjeremylt
350f2d2bf5dSjeremylt# ------------------------------------------------------------------------------
351d99fa3c5SJeremy L Thompson
352d99fa3c5SJeremy L Thompson
353d99fa3c5SJeremy L Thompsonclass _OperatorWrap(Operator):
354d99fa3c5SJeremy L Thompson    """Wrap a CeedOperator pointer in a Operator object."""
355d99fa3c5SJeremy L Thompson
356d99fa3c5SJeremy L Thompson    # Constructor
357d99fa3c5SJeremy L Thompson    def __init__(self, ceed, pointer):
358d99fa3c5SJeremy L Thompson        # CeedOperator object
359d99fa3c5SJeremy L Thompson        self._pointer = pointer
360d99fa3c5SJeremy L Thompson
361d99fa3c5SJeremy L Thompson        # Reference to Ceed
362d99fa3c5SJeremy L Thompson        self._ceed = ceed
363d99fa3c5SJeremy L Thompson
364d99fa3c5SJeremy L Thompson# ------------------------------------------------------------------------------
365