xref: /libCEED/python/ceed_operator.py (revision 69af5e5f10356896b070fd209ba6f6bf81bd32be)
1# Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at
2# the Lawrence Livermore National Laboratory. LLNL-CODE-734707. All Rights
3# reserved. See files LICENSE and NOTICE for details.
4#
5# This file is part of CEED, a collection of benchmarks, miniapps, software
6# libraries and APIs for efficient high-order finite element and spectral
7# element discretizations for exascale applications. For more information and
8# source code availability see http://github.com/ceed.
9#
10# The CEED research is supported by the Exascale Computing Project 17-SC-20-SC,
11# a collaborative effort of two U.S. Department of Energy organizations (Office
12# of Science and the National Nuclear Security Administration) responsible for
13# the planning and preparation of a capable exascale ecosystem, including
14# software, applications, hardware, advanced system engineering and early
15# testbed platforms, in support of the nation's exascale computing imperative.
16
17from _ceed_cffi import ffi, lib
18import tempfile
19from abc import ABC
20from .ceed_constants import REQUEST_IMMEDIATE, REQUEST_ORDERED, NOTRANSPOSE
21
22# ------------------------------------------------------------------------------
23
24
25class _OperatorBase(ABC):
26    """Ceed Operator: composed FE-type operations on vectors."""
27
28    # Attributes
29    _ceed = ffi.NULL
30    _pointer = ffi.NULL
31
32    # Destructor
33    def __del__(self):
34        # libCEED call
35        lib.CeedOperatorDestroy(self._pointer)
36
37    # Representation
38    def __repr__(self):
39        return "<CeedOperator instance at " + hex(id(self)) + ">"
40
41    # String conversion for print() to stdout
42    def __str__(self):
43        """View an Operator via print()."""
44
45        # libCEED call
46        with tempfile.NamedTemporaryFile() as key_file:
47            with open(key_file.name, 'r+') as stream_file:
48                stream = ffi.cast("FILE *", stream_file)
49
50                lib.CeedOperatorView(self._pointer[0], stream)
51
52                stream_file.seek(0)
53                out_string = stream_file.read()
54
55        return out_string
56
57    # Assemble linear diagonal
58    def linear_assemble_diagonal(self, d, request=REQUEST_IMMEDIATE):
59        """Assemble the diagonal of a square linear Operator
60
61           Args:
62             d: Vector to store assembled Operator diagonal
63             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
64
65        # libCEED call
66        lib.CeedOperatorLinearAssembleDiagonal(self._pointer[0],
67                                               d._pointer[0], request)
68
69    # Assemble add linear diagonal
70    def linear_assemble_add_diagonal(self, d, request=REQUEST_IMMEDIATE):
71        """Sum the diagonal of a square linear Operator into a Vector
72
73           Args:
74             d: Vector to store assembled Operator diagonal
75             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
76
77        # libCEED call
78        lib.CeedOperatorLinearAssembleAddDiagonal(self._pointer[0],
79                                                  d._pointer[0], request)
80
81    # Assemble linear point block diagonal
82    def linear_assemble_point_block_diagonal(
83            self, d, request=REQUEST_IMMEDIATE):
84        """Assemble the point block diagonal of a square linear Operator
85
86           Args:
87             d: Vector to store assembled Operator point block diagonal,
88                  provided in row-major form with an ncomp*ncomp block
89                  at each node
90             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
91
92        # libCEED call
93        lib.CeedOperatorLinearAssemblePointBlockDiagonal(self._pointer[0],
94                                                         d._pointer[0], request)
95
96    # Assemble linear point block diagonal
97    def linear_assemble_add_point_block_diagonal(
98            self, d, request=REQUEST_IMMEDIATE):
99        """Sum the point block diagonal of a square linear Operator into a Vector
100
101           Args:
102             d: Vector to store assembled Operator point block diagonal,
103                  provided in row-major form with an ncomp*ncomp block
104                  at each node
105             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
106
107        # libCEED call
108        lib.CeedOperatorLinearAssembleAddPointBlockDiagonal(self._pointer[0],
109                                                            d._pointer[0], request)
110
111    # Apply CeedOperator
112    def apply(self, u, v, request=REQUEST_IMMEDIATE):
113        """Apply Operator to a vector.
114
115           Args:
116             u: Vector containing input state or CEED_VECTOR_NONE if there are no
117                  active inputs
118             v: Vector to store result of applying operator (must be distinct from u)
119                  or CEED_VECTOR_NONE if there are no active outputs
120             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
121
122        # libCEED call
123        lib.CeedOperatorApply(self._pointer[0], u._pointer[0], v._pointer[0],
124                              request)
125
126    # Apply CeedOperator
127    def apply_add(self, u, v, request=REQUEST_IMMEDIATE):
128        """Apply Operator to a vector and add result to output vector.
129
130           Args:
131             u: Vector containing input state or CEED_VECTOR_NONE if there are no
132                  active inputs
133             v: Vector to sum in result of applying operator (must be distinct from u)
134                  or CEED_VECTOR_NONE if there are no active outputs
135             **request: Ceed request, default CEED_REQUEST_IMMEDIATE"""
136
137        # libCEED call
138        lib.CeedOperatorApplyAdd(self._pointer[0], u._pointer[0], v._pointer[0],
139                                 request)
140
141# ------------------------------------------------------------------------------
142
143
144class Operator(_OperatorBase):
145    """Ceed Operator: composed FE-type operations on vectors."""
146
147    # Constructor
148    def __init__(self, ceed, qf, dqf=None, dqfT=None):
149        # CeedOperator object
150        self._pointer = ffi.new("CeedOperator *")
151
152        # Reference to Ceed
153        self._ceed = ceed
154
155        # libCEED call
156        lib.CeedOperatorCreate(self._ceed._pointer[0], qf._pointer[0],
157                               dqf._pointer[0] if dqf else ffi.NULL,
158                               dqfT._pointer[0] if dqfT else ffi.NULL,
159                               self._pointer)
160
161    # Add field to CeedOperator
162    def set_field(self, fieldname, restriction, basis, vector):
163        """Provide a field to an Operator for use by its QFunction.
164
165           Args:
166             fieldname: name of the field (to be matched with the same name used
167                          by QFunction)
168             restriction: ElemRestriction
169             basis: Basis in which the field resides or CEED_BASIS_COLLOCATED
170                      if collocated with quadrature points
171             vector: Vector to be used by Operator or CEED_VECTOR_ACTIVE
172                       if field is active or CEED_VECTOR_NONE if using
173                       CEED_EVAL_WEIGHT in the QFunction"""
174
175        # libCEED call
176        fieldnameAscii = ffi.new("char[]", fieldname.encode('ascii'))
177        lib.CeedOperatorSetField(self._pointer[0], fieldnameAscii,
178                                 restriction._pointer[0], basis._pointer[0],
179                                 vector._pointer[0])
180
181# ------------------------------------------------------------------------------
182
183
184class CompositeOperator(_OperatorBase):
185    """Ceed Composite Operator: composition of multiple Operators."""
186
187    # Constructor
188    def __init__(self, ceed):
189        # CeedOperator object
190        self._pointer = ffi.new("CeedOperator *")
191
192        # Reference to Ceed
193        self._ceed = ceed
194        # libCEED call
195        lib.CeedCompositeOperatorCreate(self._ceed._pointer[0], self._pointer)
196
197    # Add sub operators
198    def add_sub(self, subop):
199        """Add a sub-operator to a composite CeedOperator.
200
201           Args:
202             subop: sub-operator Operator"""
203
204        # libCEED call
205        lib.CeedCompositeOperatorAddSub(self._pointer[0], subop._pointer[0])
206
207# ------------------------------------------------------------------------------
208